{"openapi":"3.0.3","info":{"title":"WitniumChain API (V5)","version":"5.0.0","description":"HTTP API for WitniumChain V5 — anchor cryptographic witnesses on the\nWitnium private Hyperledger Besu chain.\n\nV5 adds optional drand IBE time-lock per witness via two atomic fields\n(`drandRound` + `tlockCiphertext`). Without those fields a V5 witness\nis identical in shape to V4 plus a contract-derived `witnessId`.\n\nThe witness lifecycle is propose → sign (per required signer) → finalize.\n`/finalize` blocks ~10–15s on Witnium QBFT block timing so the\ncontract-derived witnessId can be returned synchronously.\n\nAuth model:\n  - Public: witness propose/sign/finalize/revoke and all reads. Auth is\n    cryptographic (Ed25519 over the canonical intent JSON).\n  - Admin Bearer: contract deploy, key management, pause/unpause. The\n    accounts service forwards owner-signed payloads using this Bearer."},"servers":[{"url":"https://api.witniumchain.com","description":"Production"},{"url":"https://chain-v3.witnium.tech","description":"Sandbox (V3 + V4 + V5)"},{"url":"http://localhost:3001","description":"Local development"}],"tags":[{"name":"Witnesses","description":"Witness lifecycle (propose / sign / finalize / revoke) and reads."},{"name":"Contracts","description":"Contract deployment, info, and existence verification."},{"name":"Keys","description":"Signing-key add / revoke (owner-signed)."},{"name":"Transactions","description":"Read on-chain transaction status + receipt detail."},{"name":"Wallets","description":"Native-token balance lookups."},{"name":"Admin","description":"Per-contract owner ops (pause/unpause) and network administration."},{"name":"Health","description":"Health checks and system status"},{"name":"Dashboard","description":"OAuth-gated read surface for the hosted Witnium dashboard. The user contract is resolved from the JWT `contract` claim (minted by accounts.witniumchain.com), not from the URL. The verification primitives at /v5/contracts/{address}/* remain public."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Bearer token authentication"}},"schemas":{},"parameters":{}},"paths":{"/v5/contracts/deploy":{"post":{"summary":"Deploy a WitnessRegistry v5 contract (Admin)","description":"Deploy a v5 contract with owner key + initial signing key. V5 adds optional drand IBE time-lock per witness (see /v5/contracts/{addr}/witnesses/propose).","tags":["Contracts"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contractId":{"type":"string","minLength":1},"ownerPublicKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"initialSigningPublicKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"strictSeries":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":{"nullable":true}}},"required":["contractId","ownerPublicKey","initialSigningPublicKey","strictSeries"],"title":"DeployContractV5Request"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"contractAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"walletAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},"blockNumber":{"type":"integer","minimum":0},"contractVersion":{"type":"string"}},"required":["contractAddress","walletAddress","transactionHash","blockNumber","contractVersion"],"title":"DeployContractV5Response"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/info":{"get":{"summary":"Get v5 contract metadata + active signing keys","description":"Returns the contract record from chain-api storage: owner key, signing keys (with addedAt/revokedAt block timestamps), strictSeries flag, current pause state, owner nonce, and deployment block. This endpoint reads chain-api storage, not the chain directly — it returns 404 if the contract was deployed outside chain-api.","tags":["Contracts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"contractAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"contractId":{"type":"string"},"contractVersion":{"type":"string"},"walletAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"ownerKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"strictSeries":{"type":"boolean"},"paused":{"type":"boolean"},"ownerNonce":{"type":"integer","minimum":0},"signingKeys":{"type":"array","items":{"type":"object","properties":{"publicKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"addedAt":{"type":"number","description":"block.timestamp at which the signing key was added"},"revokedAt":{"type":"number","description":"0 if active, else block.timestamp at revocation"}},"required":["publicKey","addedAt","revokedAt"]}},"deploymentBlockNumber":{"type":"integer","minimum":0},"isActive":{"type":"boolean"}},"required":["contractAddress","contractId","contractVersion","walletAddress","ownerKey","strictSeries","paused","ownerNonce","signingKeys","deploymentBlockNumber","isActive"],"title":"GetContractInfoV5Response"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/verify":{"get":{"summary":"Check whether an address has deployed contract bytecode","description":"Lightweight existence check: returns `exists: true` if `eth_getCode` returns non-empty bytecode at the address. Does NOT verify the contract is a WitnessRegistry V5 — that requires `/info`.","tags":["Contracts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"contractAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"exists":{"type":"boolean","description":"true if the address has deployed bytecode on the chain (any contract). Does NOT verify that the bytecode is a WitnessRegistry V5 — use /info for that."}},"required":["contractAddress","exists"],"title":"VerifyContractV5Response"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/witnesses/propose":{"post":{"summary":"Propose a v5 witness","description":"Propose a v5 witness, optionally with a drand IBE time-lock pair (drandRound + tlockCiphertext). Returns intentId + canonical intent payload to sign. Each required signer calls /sign before /finalize. The witnessId is unknown until /finalize completes.","tags":["Witnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"dataId":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"DataIdV5","description":"SHA256 hash of the witnessed data (64 hex chars)"},"requiredSigners":{"type":"array","items":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"minItems":1,"maxItems":255},"userTimestamp":{"type":"string","maxLength":128,"pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$","title":"UserTimestamp","description":"User-asserted event time as ISO 8601 UTC second-precision. Optional; when omitted, the witness has no user timestamp.","example":"2026-05-19T08:14:04Z"},"previousWitnessId":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"WitnessIdV5","description":"32-byte contract-derived witness identifier (hex, no 0x prefix)"},"metadataCommitment":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$"},"revealAfter":{"type":"integer","minimum":0},"drandRound":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":9007199254740991,"title":"DrandRound","description":"drand quicknet round number (uint64). Must be strictly in the future, and ≥60s away in wall-clock terms.","example":19000000},"tlockCiphertext":{"type":"string","minLength":72,"maxLength":8192,"pattern":"^[a-fA-F0-9]+$","title":"TlockCiphertext","description":"AGE-armored tlock ciphertext, hex-encoded UTF-8. Output of tlock-js `timelockEncrypt`. Max 4096 bytes (8192 hex chars)."},"callbackUrl":{"type":"string","format":"uri","description":"Valid URL","example":"https://example.com/path"}},"required":["dataId","requiredSigners"],"title":"ProposeWitnessV5Request"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"intentId":{"type":"string","format":"uuid","title":"IntentId","description":"UUID issued by chain-api at /propose time. Used to correlate /sign and /finalize calls. Distinct from the witnessId, which is only known once the contract mines the createWitness tx."},"witnessNonce":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$"},"payloadToSign":{"type":"string","description":"Canonical intent JSON to Ed25519-sign. JSON.stringify({dataId, userTimestamp, nonce, previousWitnessId, requiredSigners, drandRound, tlockCiphertextHash}). drandRound is 0 and tlockCiphertextHash is \"0\".repeat(64) when no time-lock."},"expiresInSeconds":{"type":"integer","minimum":0,"exclusiveMinimum":true},"requiredSigners":{"type":"array","items":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"}}},"required":["intentId","witnessNonce","payloadToSign","expiresInSeconds","requiredSigners"],"title":"ProposeWitnessV5Response"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/witnesses/{intentId}/sign":{"post":{"summary":"Submit a signature for a pending v5 witness","description":"Each required signer calls this with their pubkey + Ed25519 signature over the canonical intent JSON returned from /propose.","tags":["Witnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"},{"schema":{"type":"string","format":"uuid","title":"IntentId","description":"UUID issued by chain-api at /propose time. Used to correlate /sign and /finalize calls. Distinct from the witnessId, which is only known once the contract mines the createWitness tx."},"required":true,"description":"UUID issued by chain-api at /propose time. Used to correlate /sign and /finalize calls. Distinct from the witnessId, which is only known once the contract mines the createWitness tx.","name":"intentId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"signerPubKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"signature":{"type":"string","minLength":128,"maxLength":128,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519Signature","description":"64-byte Ed25519 signature (hex, no 0x prefix)"}},"required":["signerPubKey","signature"],"title":"SubmitSignatureV5Request"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"signaturesCollected":{"type":"integer","minimum":0},"signaturesRequired":{"type":"integer","minimum":0,"exclusiveMinimum":true},"ready":{"type":"boolean"}},"required":["signaturesCollected","signaturesRequired","ready"],"title":"SubmitSignatureV5Response"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"410":{"description":"Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/witnesses/{intentId}/finalize":{"post":{"summary":"Finalize a v5 witness (broadcast + wait for receipt)","description":"Broadcasts createWitness and blocks until the tx is mined so the contract-derived witnessId can be returned. Typical latency: 10–15s on Witnium (10s QBFT block period).","tags":["Witnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"},{"schema":{"type":"string","format":"uuid","title":"IntentId","description":"UUID issued by chain-api at /propose time. Used to correlate /sign and /finalize calls. Distinct from the witnessId, which is only known once the contract mines the createWitness tx."},"required":true,"description":"UUID issued by chain-api at /propose time. Used to correlate /sign and /finalize calls. Distinct from the witnessId, which is only known once the contract mines the createWitness tx.","name":"intentId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"intentId":{"type":"string","format":"uuid","title":"IntentId","description":"UUID issued by chain-api at /propose time. Used to correlate /sign and /finalize calls. Distinct from the witnessId, which is only known once the contract mines the createWitness tx."},"witnessId":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"WitnessIdV5","description":"32-byte contract-derived witness identifier (hex, no 0x prefix)"},"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},"blockNumber":{"type":"integer","minimum":0},"chainTimestamp":{"type":"integer","minimum":0,"description":"block.timestamp at the block that included the createWitness tx — this is the value the contract used as chainTimestamp when deriving the witnessId."},"drandRound":{"type":"integer","minimum":0,"description":"drand round encoded in the witness (0 when not time-locked)."},"status":{"type":"string"}},"required":["intentId","witnessId","transactionHash","blockNumber","chainTimestamp","drandRound","status"],"title":"FinalizeWitnessV5Response"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"410":{"description":"Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/witnesses/{witnessId}/revoke":{"post":{"summary":"Revoke a v5 witness (tombstone)","tags":["Witnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"},{"schema":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"WitnessIdV5","description":"32-byte contract-derived witness identifier (hex, no 0x prefix)"},"required":true,"description":"32-byte contract-derived witness identifier (hex, no 0x prefix)","name":"witnessId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reasonHash":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$"},"revokerPubKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"revokerSignature":{"type":"string","minLength":128,"maxLength":128,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519Signature","description":"64-byte Ed25519 signature (hex, no 0x prefix)"}},"required":["reasonHash","revokerPubKey","revokerSignature"],"title":"RevokeWitnessV5Request"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"}},"required":["transactionHash"]}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/keys":{"post":{"summary":"Add a signing key (owner-signed)","description":"Add a new Ed25519 signing key to the contract. Payload is owner-signed; the bytes signed are the canonical JSON `{op:1, contract, nonce, newKey}` (UTF-8, no whitespace). The Admin bearer token authenticates the caller (typically the accounts service forwarding the owner-signed payload). Owner-op `op` codes (numeric, match on-chain): 1=addSigningKey, 2=revokeSigningKey, 3=pause, 4=unpause.","tags":["Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"newKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"ownerNonce":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Monotonic owner nonce. Read the current value from /v5/contracts/{addr}/info as `ownerNonce`, then use `ownerNonce + 1` here."},"ownerSignature":{"type":"string","minLength":128,"maxLength":128,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519Signature","description":"64-byte Ed25519 signature (hex, no 0x prefix)"}},"required":["newKey","ownerNonce","ownerSignature"],"title":"AddSigningKeyV5Request"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"}},"required":["transactionHash"],"title":"OwnerOpV5Response"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/keys/revoke":{"post":{"summary":"Revoke a signing key (owner-signed)","description":"Revoke an existing Ed25519 signing key. Once revoked, the key cannot create new witnesses but previously-created witnesses are unaffected. The bytes signed are the canonical JSON `{op:2, contract, nonce, key}` (UTF-8, no whitespace). Owner-op `op` codes (numeric, match on-chain): 1=addSigningKey, 2=revokeSigningKey, 3=pause, 4=unpause.","tags":["Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"keyToRevoke":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"ownerNonce":{"type":"integer","minimum":0,"exclusiveMinimum":true},"ownerSignature":{"type":"string","minLength":128,"maxLength":128,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519Signature","description":"64-byte Ed25519 signature (hex, no 0x prefix)"}},"required":["keyToRevoke","ownerNonce","ownerSignature"],"title":"RevokeSigningKeyV5Request"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"}},"required":["transactionHash"],"title":"OwnerOpV5Response"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/pause":{"post":{"summary":"Pause a contract (owner-signed)","description":"Pause witness creation on the contract. While paused, /propose/sign/finalize reject. Reads continue to work. Pair with /unpause to resume. The bytes signed are the canonical JSON `{op:3, contract, nonce}` (UTF-8, no whitespace). Owner-op `op` codes (numeric, match on-chain): 1=addSigningKey, 2=revokeSigningKey, 3=pause, 4=unpause.","tags":["Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ownerNonce":{"type":"integer","minimum":0,"exclusiveMinimum":true},"ownerSignature":{"type":"string","minLength":128,"maxLength":128,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519Signature","description":"64-byte Ed25519 signature (hex, no 0x prefix)"}},"required":["ownerNonce","ownerSignature"],"title":"PauseV5Request"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"}},"required":["transactionHash"],"title":"OwnerOpV5Response"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/unpause":{"post":{"summary":"Unpause a contract (owner-signed)","description":"Inverse of /pause. The bytes signed are the canonical JSON `{op:4, contract, nonce}` (UTF-8, no whitespace). Owner-op `op` codes (numeric, match on-chain): 1=addSigningKey, 2=revokeSigningKey, 3=pause, 4=unpause.","tags":["Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ownerNonce":{"type":"integer","minimum":0,"exclusiveMinimum":true},"ownerSignature":{"type":"string","minLength":128,"maxLength":128,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519Signature","description":"64-byte Ed25519 signature (hex, no 0x prefix)"}},"required":["ownerNonce","ownerSignature"],"title":"PauseV5Request"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"}},"required":["transactionHash"],"title":"OwnerOpV5Response"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/witnesses":{"get":{"summary":"List v5 witnesses (optionally filtered by dataId)","description":"Scans the WitnessCreated event log from contract deployment to head. The v5 event adds drandRound — non-zero means the witness carries a drand IBE ciphertext decryptable at that round. Query the full witness via /get for the ciphertext bytes.","tags":["Witnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"},{"schema":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$"},"required":false,"name":"dataId","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"witnesses":{"type":"array","items":{"type":"object","properties":{"witnessId":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"WitnessIdV5","description":"32-byte contract-derived witness identifier (hex, no 0x prefix)"},"dataId":{"type":"string"},"timestamp":{"type":"number"},"blockNumber":{"type":"number"},"previousWitnessId":{"type":"string","nullable":true},"signerCount":{"type":"number"},"timeLocked":{"type":"boolean"},"hasUserTimestamp":{"type":"boolean"},"drandRound":{"type":"integer","minimum":0}},"required":["witnessId","dataId","timestamp","blockNumber","previousWitnessId","signerCount","timeLocked","hasUserTimestamp","drandRound"]}},"hasMore":{"type":"boolean"},"totalReturned":{"type":"number"}},"required":["witnesses","hasMore","totalReturned"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/witnesses/{witnessId}":{"get":{"summary":"Get a single v5 witness by ID","description":"Returns the full on-chain witness record. For time-locked witnesses (drandRound != 0), the `tlockCiphertext` is returned as hex-encoded AGE-armored bytes; decrypt it via MCP `reveal_witness` after the drand round publishes.","tags":["Witnesses"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"},{"schema":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"WitnessIdV5","description":"32-byte contract-derived witness identifier (hex, no 0x prefix)"},"required":true,"description":"32-byte contract-derived witness identifier (hex, no 0x prefix)","name":"witnessId","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"witnessId":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"WitnessIdV5","description":"32-byte contract-derived witness identifier (hex, no 0x prefix)"},"dataId":{"type":"string","description":"SHA256 of the witnessed data, as 64 hex chars."},"timestamp":{"type":"number","description":"block.timestamp at the block that created the witness"},"blockNumber":{"type":"number"},"previousWitnessId":{"type":"string","nullable":true,"description":"Witness ID this witness chains from, or null. Used by strictSeries contracts to enforce a single linear chain."},"nonce":{"type":"string","description":"Per-witness nonce (64 hex chars). Generated by chain-api at /propose time."},"metadataCommitment":{"type":"string","description":"32-byte commitment to off-chain metadata, or \"0\".repeat(64) if none."},"revealAfter":{"type":"number","description":"Legacy time-lock unix timestamp from V3/V4 — left for shape compatibility. For real time-lock use `drandRound` + `tlockCiphertext` instead."},"userTimestamp":{"type":"string","description":"User-asserted event time as ISO 8601 UTC second-precision, or \"\" if none was supplied at propose time."},"revokedAt":{"type":"number","description":"0 if active, else block.timestamp at revocation."},"revokedReason":{"type":"string","description":"32-byte hash of the revocation reason, or \"0\".repeat(64) if never revoked."},"sealed":{"type":"boolean","description":"true if `revealAfter` is set and still in the future. Sealed witnesses redact `userTimestamp` to \"\". Not related to drand time-lock."},"exists":{"type":"boolean"},"drandRound":{"type":"integer","minimum":0,"description":"drand quicknet round at which `tlockCiphertext` becomes decryptable. 0 means the witness is not drand-time-locked."},"tlockCiphertext":{"type":"string","description":"AGE-armored ciphertext, hex-encoded UTF-8. Empty string when the witness is not drand-time-locked. Decrypt via MCP `reveal_witness` after `drandRound` has published."},"signers":{"type":"array","items":{"type":"object","properties":{"pubKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"sigR":{"type":"string","description":"R component of the Ed25519 signature, 32 hex chars."},"sigS":{"type":"string","description":"S component of the Ed25519 signature, 32 hex chars."}},"required":["pubKey","sigR","sigS"]}}},"required":["witnessId","dataId","timestamp","blockNumber","previousWitnessId","nonce","metadataCommitment","revealAfter","userTimestamp","revokedAt","revokedReason","sealed","exists","drandRound","tlockCiphertext","signers"],"title":"GetWitnessV5Response"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/transactions/{txHash}":{"get":{"summary":"Get transaction status","description":"Lightweight mempool + chain lookup for a tx hash. Use this to poll a tx after /finalize or any owner op until it confirms.","tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},"required":true,"description":"Ethereum transaction hash (0x + 64 hex characters)","name":"txHash","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},"blockNumber":{"type":"integer","nullable":true,"description":"Block number if mined, null if still pending in mempool."},"status":{"type":"string","enum":["pending","confirmed","not-found"],"description":"`confirmed` once mined into a block; `pending` if in mempool but not mined; `not-found` if no node has seen it."}},"required":["transactionHash","blockNumber","status"],"title":"GetTransactionStatusV5Response"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/contracts/{contractAddress}/transactions/{txHash}":{"get":{"summary":"Get full transaction details","description":"Returns receipt-level detail: block + timestamp + gas + sender/recipient. `contractAddress` is contextual (not used in the lookup) — included so consumers can scope tx lookups to a contract namespace.","tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"contractAddress","in":"path"},{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},"required":true,"description":"Ethereum transaction hash (0x + 64 hex characters)","name":"txHash","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","nullable":true,"properties":{"transactionHash":{"type":"string","pattern":"^0x[a-fA-F0-9]{64}$","description":"Ethereum transaction hash (0x + 64 hex characters)","example":"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"},"blockNumber":{"type":"integer","minimum":0},"blockHash":{"type":"string","description":"0x-prefixed 32-byte block hash that included the tx."},"blockTimestamp":{"type":"integer","minimum":0,"description":"block.timestamp (unix seconds) of the including block."},"transactionIndex":{"type":"integer","minimum":0},"gasUsed":{"type":"string","description":"Decimal string (wei units of gas units), big-int-safe."},"effectiveGasPrice":{"type":"string","description":"Decimal string (wei per gas unit), big-int-safe."},"from":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"to":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"}},"required":["transactionHash","blockNumber","blockHash","blockTimestamp","transactionIndex","gasUsed","effectiveGasPrice","from","to"],"title":"GetTransactionDetailsV5Response","description":"null if the tx is not yet mined or does not exist; full object once confirmed."}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/wallets/{address}/balance":{"get":{"summary":"Get the native-token balance of an address","description":"Returns the address balance in both ETH-formatted and wei representations. Useful for checking that a per-contract wallet has gas to fund subsequent createWitness txs.","tags":["Wallets"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"address","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"balanceEth":{"type":"string","description":"Balance formatted as ETH (decimal string, 18-decimal place).","example":"1.234567890123456789"},"balanceWei":{"type":"string","description":"Balance in wei (big-int as decimal string).","example":"1234567890123456789"}},"required":["address","balanceEth","balanceWei"],"title":"GetWalletBalanceV5Response"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/dashboard/witnesses":{"get":{"summary":"List the authenticated user's witnesses, filtered (newest-first)","description":"Returns paginated witness headers for the contract resolved from the OAuth\nJWT `contract` claim. Filters are applied during the event scan:\n\n- `from` / `to`: unix-second range over `block.timestamp`\n- `timeLock`: structural filter on whether the witness carries a drandRound\n\nResponse shape is identical to GET /v5/contracts/{addr}/witnesses; the\nscan is always newest-first.","tags":["Dashboard"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Filter to witnesses with block.timestamp >= this unix-second value.","example":1731000000},"required":false,"description":"Filter to witnesses with block.timestamp >= this unix-second value.","name":"from","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Filter to witnesses with block.timestamp <= this unix-second value.","example":1736000000},"required":false,"description":"Filter to witnesses with block.timestamp <= this unix-second value.","name":"to","in":"query"},{"schema":{"type":"string","enum":["locked","none","any"],"description":"Filter by drand IBE time-lock state. \"locked\" = witness has a drandRound, \"none\" = no time-lock, \"any\" = no filter (default)."},"required":false,"description":"Filter by drand IBE time-lock state. \"locked\" = witness has a drandRound, \"none\" = no time-lock, \"any\" = no filter (default).","name":"timeLock","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size, 1-200, default 50."},"required":false,"description":"Page size, 1-200, default 50.","name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Offset into the filtered set, default 0."},"required":false,"description":"Offset into the filtered set, default 0.","name":"offset","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"witnesses":{"type":"array","items":{"type":"object","properties":{"witnessId":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"WitnessIdV5","description":"32-byte contract-derived witness identifier (hex, no 0x prefix)"},"dataId":{"type":"string"},"timestamp":{"type":"number"},"blockNumber":{"type":"number"},"previousWitnessId":{"type":"string","nullable":true},"signerCount":{"type":"number"},"timeLocked":{"type":"boolean"},"hasUserTimestamp":{"type":"boolean"},"drandRound":{"type":"integer","minimum":0}},"required":["witnessId","dataId","timestamp","blockNumber","previousWitnessId","signerCount","timeLocked","hasUserTimestamp","drandRound"]}},"hasMore":{"type":"boolean"},"totalReturned":{"type":"number"}},"required":["witnesses","hasMore","totalReturned"]}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/v5/dashboard/contract":{"get":{"summary":"Get the authenticated user's contract info","description":"Returns the contract record for the contract resolved from the OAuth JWT\n`contract` claim — same shape as GET /v5/contracts/{addr}/info, but with\nno address in the URL: identity is taken from the bearer token.","tags":["Dashboard"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"contractAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"contractId":{"type":"string"},"contractVersion":{"type":"string"},"walletAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"ownerKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"strictSeries":{"type":"boolean"},"paused":{"type":"boolean"},"ownerNonce":{"type":"integer","minimum":0},"signingKeys":{"type":"array","items":{"type":"object","properties":{"publicKey":{"type":"string","minLength":64,"maxLength":64,"pattern":"^[a-fA-F0-9]+$","title":"Ed25519PublicKey","description":"32-byte Ed25519 public key (hex, no 0x prefix)"},"addedAt":{"type":"number","description":"block.timestamp at which the signing key was added"},"revokedAt":{"type":"number","description":"0 if active, else block.timestamp at revocation"}},"required":["publicKey","addedAt","revokedAt"]}},"deploymentBlockNumber":{"type":"integer","minimum":0},"isActive":{"type":"boolean"}},"required":["contractAddress","contractId","contractVersion","walletAddress","ownerKey","strictSeries","paused","ownerNonce","signingKeys","deploymentBlockNumber","isActive"],"title":"GetContractInfoV5Response"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/admin/validators/propose":{"post":{"summary":"Propose adding or removing a validator","description":"Submit a vote to add or remove a validator from the network.","tags":["Admin"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"validatorAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"add":{"type":"boolean","description":"true = vote to add, false = vote to remove"}},"required":["validatorAddress","add"],"title":"ProposeValidatorRequest","description":"Request to propose adding or removing a validator"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"validatorAddress":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"add":{"type":"boolean"},"message":{"type":"string"}},"required":["success","validatorAddress","add","message"],"title":"ProposeValidatorResponse","description":"Validator proposal result"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/admin/validators/vote/{address}":{"delete":{"summary":"Discard a vote for a validator","description":"Remove a vote for adding or removing a validator.","tags":["Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"required":true,"description":"Ethereum address (0x + 40 hex characters)","name":"address","in":"path"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"message":{"type":"string"}},"required":["success","message"],"title":"DiscardVoteResponse","description":"Vote discard result"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/admin/validators":{"get":{"summary":"Get list of validators","description":"Get the current list of validators in the network.","tags":["Admin"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"validators":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"added":{"type":"boolean"}},"required":["address","added"],"title":"Validator","description":"Validator information"}}},"required":["validators"],"title":"GetValidatorsResponse","description":"List of validators"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/admin/validators/pending":{"get":{"summary":"Get list of pending validators","description":"Get validators that have votes but are not yet added/removed.","tags":["Admin"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"pending":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"addVotes":{"type":"integer","minimum":0},"removeVotes":{"type":"integer","minimum":0}},"required":["address","addVotes","removeVotes"],"title":"PendingValidator","description":"Pending validator vote information"}}},"required":["pending"],"title":"GetPendingValidatorsResponse","description":"List of pending validators"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/admin/network/status":{"get":{"summary":"Get network status","description":"Get the current status of the blockchain network.","tags":["Admin"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"blockNumber":{"type":"integer","minimum":0},"validatorCount":{"type":"integer","minimum":0}},"required":["chainId","blockNumber","validatorCount"],"title":"NetworkStatusResponse","description":"Network status information"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/admin/network/peers":{"get":{"summary":"Get network peers","description":"Get the list of connected network peers.","tags":["Admin"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"peers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"enode":{"type":"string"},"status":{"type":"string","enum":["connected","disconnected"]}},"required":["id","enode","status"],"title":"Peer","description":"Network peer information"}}},"required":["peers"],"title":"GetNetworkPeersResponse","description":"List of network peers"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}},"post":{"summary":"Add a network peer","description":"Add a peer to the network.","tags":["Admin"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"enode":{"type":"string","minLength":1}},"required":["enode"],"title":"AddPeerRequest","description":"Request to add a network peer"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"message":{"type":"string"}},"required":["success","message"],"title":"AddPeerResponse","description":"Peer addition result"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}},"delete":{"summary":"Remove a network peer","description":"Remove a peer from the network.","tags":["Admin"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"enode":{"type":"string","minLength":1}},"required":["enode"],"title":"RemovePeerRequest","description":"Request to remove a network peer"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"message":{"type":"string"}},"required":["success","message"],"title":"RemovePeerResponse","description":"Peer removal result"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/admin/utils/pubkey-to-address":{"post":{"summary":"Convert public key to Ethereum address","description":"Utility endpoint to convert a public key to an Ethereum address.","tags":["Admin"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"pubkey":{"type":"string","minLength":1}},"required":["pubkey"],"title":"PubkeyToAddressRequest","description":"Request to convert public key to Ethereum address"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Ethereum address (0x + 40 hex characters)","example":"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"},"pubkey":{"type":"string"}},"required":["address","pubkey"],"title":"PubkeyToAddressResponse","description":"Ethereum address derived from public key"}}}},"400":{"description":"Bad Request - Validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/health/live":{"get":{"summary":"Liveness probe","description":"Kubernetes liveness probe. Fails if queue connection lost for > 1 minute.","tags":["Health"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy"]},"queue":{"type":"object","properties":{"healthy":{"type":"boolean"},"timeSinceLastPingMs":{"type":"integer","minimum":0},"lastPing":{"type":"string","format":"date-time"}},"required":["healthy","timeSinceLastPingMs"],"title":"QueueStatus","description":"Queue health status"}},"required":["status","queue"],"title":"LivenessResponse","description":"Liveness probe response"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/health/ready":{"get":{"summary":"Readiness probe","description":"Kubernetes readiness probe. Fails if queue or blockchain is unhealthy.","tags":["Health"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ready"]},"queue":{"type":"object","properties":{"healthy":{"type":"boolean"},"timeSinceLastPingMs":{"type":"integer","minimum":0},"lastPing":{"type":"string","format":"date-time"}},"required":["healthy","timeSinceLastPingMs"],"title":"QueueStatus","description":"Queue health status"},"blockchain":{"type":"object","properties":{"connected":{"type":"boolean"},"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"blockNumber":{"type":"integer","minimum":0}},"required":["connected"],"title":"BlockchainStatus","description":"Blockchain connection status"}},"required":["status","queue","blockchain"],"title":"ReadinessResponse","description":"Readiness probe response"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}},"/health":{"get":{"summary":"Detailed health check","description":"Get detailed health status for debugging. Not used for K8s probes.","tags":["Health"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded"]},"timestamp":{"type":"string","format":"date-time"},"queue":{"type":"object","properties":{"healthy":{"type":"boolean"},"timeSinceLastPingMs":{"type":"integer","minimum":0},"lastPing":{"type":"string","format":"date-time"}},"required":["healthy","timeSinceLastPingMs"],"title":"QueueStatus","description":"Queue health status"},"blockchain":{"type":"object","properties":{"connected":{"type":"boolean"},"chainId":{"type":"integer","minimum":0,"exclusiveMinimum":true},"blockNumber":{"type":"integer","minimum":0}},"required":["connected"],"title":"BlockchainStatus","description":"Blockchain connection status"},"redis":{"type":"object","properties":{"connected":{"type":"boolean"}},"required":["connected"],"title":"RedisStatus","description":"Redis connection status"}},"required":["status","timestamp","queue","blockchain"],"title":"HealthResponse","description":"Detailed health status"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","description":"Error message","example":"Validation failed"},"code":{"type":"string","description":"Machine-readable error code","example":"VALIDATION_FAILED"},"details":{"type":"object","description":"Field-level validation errors","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["error"],"title":"ErrorResponse","description":"Standard error response format"}}}}}}}}}