{"openapi":"3.0.0","paths":{"/":{"get":{"description":"Hitting the root of the domain redirects to /docs and a swagger deployment.","operationId":"AppController_redirect","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Redirect to the API docs","tags":["System"]}},"/v1/_health":{"get":{"description":"This endpoint reports the API and its dependencies health.","operationId":"HealthController_check_v1","parameters":[],"responses":{"200":{"description":"The Health Check is successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"info":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"error":{"type":"object","example":{},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"details":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true}}}}}}},"503":{"description":"The Health Check is not successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"error"},"info":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"error":{"type":"object","example":{"redis":{"status":"down","message":"Could not connect"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"details":{"type":"object","example":{"database":{"status":"up"},"redis":{"status":"down","message":"Could not connect"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true}}}}}}}},"summary":"Check the API health","tags":["System"]}},"/metrics":{"get":{"operationId":"MetricsController_metrics","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}}},"tags":["Metrics"]}},"/v1/definition/{configHash}":{"get":{"description":"This endpoint allows a charon client or launchpad interface to retrieve the terms of a proposed DKG. Once all operators listed in the DKG have submitted signed approvals to the terms, this object will be ready for a cluster of operators to use as part of a DKG ceremony. If the objects in the `operators` array are not fully populated, these operators need to use the [PUT request](#/Distributed%20Validators/DefinitionController_updateClusterDefinition) to upload their charon client's public key and a signature from their address to indicate their acceptance of the terms.","operationId":"DefinitionController_getClusterDefinition_v1","parameters":[{"name":"configHash","required":true,"in":"path","description":"The `config_hash` calculated for a cluster definition.","schema":{"type":"string"}}],"responses":{"200":{"description":"The cluster object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterDefinitionResponse"}]}}}},"404":{"description":"Cluster definition not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a Distributed Validator Cluster proposal","tags":["Cluster Definition"]},"put":{"description":"This endpoint is used by the operators present in the `operators` array of a cluster definition. The operator must have accepted the latest version of [Obol's terms and conditions](https://obol.tech/terms.pdf). These operators must submit a public key (in ENR form) to serve as their identity during the DKG, along with EIP712 signatures indicating their acceptance of the terms of this DKG.","operationId":"DefinitionController_updateClusterDefinition_v1","parameters":[{"name":"authorization","required":true,"in":"header","description":"EIP712 operator hash as bearer token","schema":{"type":"string"}},{"name":"configHash","required":true,"in":"path","description":"The `config_hash` calculated for a cluster definition.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperatorDto"}}}},"responses":{"200":{"description":"The cluster object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterDefinitionResponse"}]}}}},"400":{"description":"Invalid payload data"},"401":{"description":"Authorization header is missing or incorrect"},"404":{"description":"Data not found"},"409":{"description":"Duplicate entry"},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Accept a proposed Distributed Validator Cluster","tags":["Cluster Definition"]}},"/v1/definition/operator/{address}":{"get":{"description":"This endpoint allows a charon client or launchpad interface to fetch a specific number of cluster definitions which the address is part of for each page.","operationId":"DefinitionController_getClusterDefinitionWithOperator_v1","parameters":[{"name":"address","required":true,"in":"path","description":"The operator address","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"A list of cluster definitions which the operator is part of","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterDefinitionPagedResponse"}]}}}},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of cluster definitions which the address belongs to.","tags":["Cluster Definition"]}},"/v1/definition":{"post":{"description":"This endpoint allows the caller to propose a distributed key generation ceremony.The caller must have accepted the latest version of [Obol's terms and conditions](https://obol.tech/terms.pdf). The caller must specify the configuration of a Distributed Validator Cluster; such as the participating operators and the validator exit details. Operators invited to participate in this cluster must submit a public key (in [ENR](https://docs.obol.tech/docs/v0.12.0/int/faq/errors#enrs-keys) form) to serve as their node's identity, along with EIP712 signatures indicating their acceptance of the terms of this cluster.","operationId":"DefinitionController_postClusterDefinition_v1","parameters":[{"name":"authorization","required":true,"in":"header","description":"EIP712 cluster definition hash as bearer token","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterDefDto"}}}},"responses":{"201":{"description":"The cluster object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterDefinitionResponse"}]}}}},"400":{"description":"Invalid definition data"},"401":{"description":"Authorization header is missing or incorrect"},"409":{"description":"Duplicate entry"},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Propose a new Distributed Validator Cluster","tags":["Cluster Definition"]}},"/lock/{lockHash}":{"get":{"description":"This endpoint is used to retrieve a cluster lock object.","operationId":"LockController_getClusterLock[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lock_hash` calculated for a cluster lock.","schema":{"type":"string"}}],"responses":{"200":{"description":"The cluster lock object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockResponse"}]}}}},"404":{"description":"Cluster not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a Distributed Validator Cluster Lock Object","tags":["Cluster Lock"]}},"/v1/lock/{lockHash}":{"get":{"description":"This endpoint is used to retrieve a cluster lock object.","operationId":"LockController_getClusterLock[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lock_hash` calculated for a cluster lock.","schema":{"type":"string"}}],"responses":{"200":{"description":"The cluster lock object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockResponse"}]}}}},"404":{"description":"Cluster not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a Distributed Validator Cluster Lock Object","tags":["Cluster Lock"]}},"/lock/search/{network}":{"get":{"description":"This endpoint is used to search for Cluster Lock Objects that match a substring of their `lock_hash`.","operationId":"LockController_searchClusterLocks[0]","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve clusters on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"partialLockHash","required":true,"in":"query","description":"A substring of the `lock_hash` calculated for a cluster lock.","schema":{"type":"string"}},{"name":"partialClusterName","required":true,"in":"query","description":"A substring of the cluster name.","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"limit","required":true,"in":"query","description":"The number of cluster lock objects to return.","schema":{"type":"integer","default":100}}],"responses":{"200":{"description":"A list of Distributed Validator Clusters which the lock hash matches.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockPagedResponse"}]}}}},"404":{"description":"Cluster not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of Distributed Validator Cluster Lock Objects","tags":["Cluster Lock"]}},"/v1/lock/search/{network}":{"get":{"description":"This endpoint is used to search for Cluster Lock Objects that match a substring of their `lock_hash`.","operationId":"LockController_searchClusterLocks[1]_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve clusters on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"partialLockHash","required":true,"in":"query","description":"A substring of the `lock_hash` calculated for a cluster lock.","schema":{"type":"string"}},{"name":"partialClusterName","required":true,"in":"query","description":"A substring of the cluster name.","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"limit","required":true,"in":"query","description":"The number of cluster lock objects to return.","schema":{"type":"integer","default":100}}],"responses":{"200":{"description":"A list of Distributed Validator Clusters which the lock hash matches.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockPagedResponse"}]}}}},"404":{"description":"Cluster not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of Distributed Validator Cluster Lock Objects","tags":["Cluster Lock"]}},"/lock/configHash/{configHash}":{"get":{"description":"This endpoint is used to retrieve a cluster lock object by the hash of the configuration used to create it.","operationId":"LockController_getLockByConfigHash[0]","parameters":[{"name":"configHash","required":true,"in":"path","description":"The `config_hash` calculated for a cluster configuration.","schema":{"type":"string"}}],"responses":{"200":{"description":"The cluster lock object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockResponse"}]}}}},"404":{"description":"Cluster not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a Distributed Validator Cluster Lock Object","tags":["Cluster Lock"]}},"/v1/lock/configHash/{configHash}":{"get":{"description":"This endpoint is used to retrieve a cluster lock object by the hash of the configuration used to create it.","operationId":"LockController_getLockByConfigHash[1]_v1","parameters":[{"name":"configHash","required":true,"in":"path","description":"The `config_hash` calculated for a cluster configuration.","schema":{"type":"string"}}],"responses":{"200":{"description":"The cluster lock object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockResponse"}]}}}},"404":{"description":"Cluster not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a Distributed Validator Cluster Lock Object","tags":["Cluster Lock"]}},"/lock/{lockHash}/launchpad":{"get":{"description":"This endpoint is used to redirect users to the created cluster status page after DKG is completed.","operationId":"LockController_redirectToClusterStatus[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lock_hash` calculated for a Distributed Validator Cluster.","schema":{"type":"string"}}],"responses":{"200":{"description":""},"302":{"description":"Serves a redirect to the launchpad cluster status page"},"404":{"description":"Cluster lock not found"},"500":{"description":"An unknown error occurred"}},"summary":"Redirect to the launchpad cluster status page","tags":["Cluster Lock"]}},"/v1/lock/{lockHash}/launchpad":{"get":{"description":"This endpoint is used to redirect users to the created cluster status page after DKG is completed.","operationId":"LockController_redirectToClusterStatus[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lock_hash` calculated for a Distributed Validator Cluster.","schema":{"type":"string"}}],"responses":{"200":{"description":""},"302":{"description":"Serves a redirect to the launchpad cluster status page"},"404":{"description":"Cluster lock not found"},"500":{"description":"An unknown error occurred"}},"summary":"Redirect to the launchpad cluster status page","tags":["Cluster Lock"]}},"/lock/{lockHash}/peer-scores":{"get":{"description":"This endpoint returns the average peer_score for each operator address in a cluster lock within a specified date range. Results are sorted by peer_score in descending order.","operationId":"LockController_getAveragePeerScores[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lock_hash` calculated for a cluster lock.","schema":{"type":"string"}},{"name":"startDate","required":false,"in":"query","description":"Start date for the range (ISO 8601 format). If not provided, defaults to endDate - 7 days.","schema":{"example":"2026-01-21T00:00:00.000Z","type":"string"}},{"name":"endDate","required":false,"in":"query","description":"End date for the range (ISO 8601 format). If not provided, defaults to the latest available date.","schema":{"example":"2026-01-28T00:00:00.000Z","type":"string"}}],"responses":{"200":{"description":"Array of operator addresses with their average peer scores","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"operator_address":{"type":"string","example":"0x7a82E643B0c8AE619f71d9667559180c33c92277"},"avg_peer_score":{"type":"number","example":99.89}}}}}}},"400":{"description":"Invalid date format"},"404":{"description":"Cluster lock not found"},"500":{"description":"An unknown error occurred"}},"summary":"Get average peer scores for operators in a cluster","tags":["Cluster Lock"]}},"/v1/lock/{lockHash}/peer-scores":{"get":{"description":"This endpoint returns the average peer_score for each operator address in a cluster lock within a specified date range. Results are sorted by peer_score in descending order.","operationId":"LockController_getAveragePeerScores[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lock_hash` calculated for a cluster lock.","schema":{"type":"string"}},{"name":"startDate","required":false,"in":"query","description":"Start date for the range (ISO 8601 format). If not provided, defaults to endDate - 7 days.","schema":{"example":"2026-01-21T00:00:00.000Z","type":"string"}},{"name":"endDate","required":false,"in":"query","description":"End date for the range (ISO 8601 format). If not provided, defaults to the latest available date.","schema":{"example":"2026-01-28T00:00:00.000Z","type":"string"}}],"responses":{"200":{"description":"Array of operator addresses with their average peer scores","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"operator_address":{"type":"string","example":"0x7a82E643B0c8AE619f71d9667559180c33c92277"},"avg_peer_score":{"type":"number","example":99.89}}}}}}},"400":{"description":"Invalid date format"},"404":{"description":"Cluster lock not found"},"500":{"description":"An unknown error occurred"}},"summary":"Get average peer scores for operators in a cluster","tags":["Cluster Lock"]}},"/lock/operator/{address}":{"get":{"description":"This endpoint fetches a number of Distributed Validator Clusters for which the address provided is a node operator.","operationId":"LockController_getClusterLocksByOperator[0]","parameters":[{"name":"address","required":true,"in":"path","description":"The operator address.","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"limit","required":true,"in":"query","description":"The number of cluster lock objects to return.","schema":{"type":"integer","default":100}}],"responses":{"200":{"description":"A list of Distributed Validator Clusters which the operator is a member of.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockPagedResponse"}]}}}},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of Distributed Validator Clusters for which this address is an operator","tags":["Cluster Lock"]}},"/v1/lock/operator/{address}":{"get":{"description":"This endpoint fetches a number of Distributed Validator Clusters for which the address provided is a node operator.","operationId":"LockController_getClusterLocksByOperator[1]_v1","parameters":[{"name":"address","required":true,"in":"path","description":"The operator address.","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"limit","required":true,"in":"query","description":"The number of cluster lock objects to return.","schema":{"type":"integer","default":100}}],"responses":{"200":{"description":"A list of Distributed Validator Clusters which the operator is a member of.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockPagedResponse"}]}}}},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of Distributed Validator Clusters for which this address is an operator","tags":["Cluster Lock"]}},"/lock/network/{network}":{"get":{"description":"This endpoint fetches a number of cluster lock objects for a given network.","operationId":"LockController_getClusterLocksByNetwork[0]","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve clusters on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"limit","required":true,"in":"query","description":"The number of cluster lock objects to return.","schema":{"type":"integer","default":100}},{"name":"sortBy","required":false,"in":"query","description":"numerical field to sort by","schema":{"type":"string","default":"avg_effectiveness"}},{"name":"sortOrder","required":false,"in":"query","description":"order of sorting the field","schema":{"type":"string","default":"desc"}},{"name":"pool","required":false,"in":"query","description":"cluster type or pool","schema":{"type":"string"}},{"name":"details","required":true,"in":"query","description":"The flag to populate cluster definition information.","schema":{"type":"string","default":"false"}}],"responses":{"200":{"description":"A paged list of Distributed Validator Clusters on this network","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockPagedResponse"}]}}}},"400":{"description":"Network not spported"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of Distributed Validator Clusters for a given network","tags":["Cluster Lock"]}},"/v1/lock/network/{network}":{"get":{"description":"This endpoint fetches a number of cluster lock objects for a given network.","operationId":"LockController_getClusterLocksByNetwork[1]_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve clusters on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"limit","required":true,"in":"query","description":"The number of cluster lock objects to return.","schema":{"type":"integer","default":100}},{"name":"sortBy","required":false,"in":"query","description":"numerical field to sort by","schema":{"type":"string","default":"avg_effectiveness"}},{"name":"sortOrder","required":false,"in":"query","description":"order of sorting the field","schema":{"type":"string","default":"desc"}},{"name":"pool","required":false,"in":"query","description":"cluster type or pool","schema":{"type":"string"}},{"name":"details","required":true,"in":"query","description":"The flag to populate cluster definition information.","schema":{"type":"string","default":"false"}}],"responses":{"200":{"description":"A paged list of Distributed Validator Clusters on this network","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockPagedResponse"}]}}}},"400":{"description":"Network not spported"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of Distributed Validator Clusters for a given network","tags":["Cluster Lock"]}},"/lock/network/summary/{network}":{"get":{"description":"This endpoint fetches a nsummary of the lock files stored for a given network","operationId":"LockController_getClusterLockNetworkSummary[0]","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve clusters on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"}},"schema":{"type":"string"}}],"responses":{"200":{"description":"A summary of the Distributed Validator locks for a given network","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockNetworkSummaryResponse"}]}}}},"400":{"description":"Network not spported"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of Distributed Validator Clusters for a given network","tags":["Cluster Lock"]}},"/v1/lock/network/summary/{network}":{"get":{"description":"This endpoint fetches a nsummary of the lock files stored for a given network","operationId":"LockController_getClusterLockNetworkSummary[1]_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve clusters on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"}},"schema":{"type":"string"}}],"responses":{"200":{"description":"A summary of the Distributed Validator locks for a given network","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockNetworkSummaryResponse"}]}}}},"400":{"description":"Network not spported"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list of Distributed Validator Clusters for a given network","tags":["Cluster Lock"]}},"/lock":{"post":{"description":"This endpoint saves cluster lock objects that describe the created Distributed Validator Cluster.","operationId":"LockController_postClusterLock[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterLockDto"}}}},"responses":{"201":{"description":"The cluster lock object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockResponse"}]}}}},"400":{"description":"Invalid lock data"},"404":{"description":"The cluster definition corresponding to this lock file was not found"},"409":{"description":"Duplicate cluster lock entry"},"500":{"description":"An unknown error occurred"}},"summary":"Push Distributed Validator Cluster Lock Data","tags":["Cluster Lock"]}},"/v1/lock":{"post":{"description":"This endpoint saves cluster lock objects that describe the created Distributed Validator Cluster.","operationId":"LockController_postClusterLock[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterLockDto"}}}},"responses":{"201":{"description":"The cluster lock object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterLockResponse"}]}}}},"400":{"description":"Invalid lock data"},"404":{"description":"The cluster definition corresponding to this lock file was not found"},"409":{"description":"Duplicate cluster lock entry"},"500":{"description":"An unknown error occurred"}},"summary":"Push Distributed Validator Cluster Lock Data","tags":["Cluster Lock"]}},"/lock/verify":{"post":{"description":"This endpoint verifies cluster lock data including BLS public keys and signatures created during the DKG phase.","operationId":"LockController_verifyClusterLock[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterLockDto"}}}},"responses":{"200":{"description":"Lock data is valid"},"400":{"description":"Invalid lock data"},"500":{"description":"An unknown error occurred"}},"summary":"Verify Distributed Validator Cluster Lock Data","tags":["Cluster Lock"]}},"/v1/lock/verify":{"post":{"description":"This endpoint verifies cluster lock data including BLS public keys and signatures created during the DKG phase.","operationId":"LockController_verifyClusterLock[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterLockDto"}}}},"responses":{"200":{"description":"Lock data is valid"},"400":{"description":"Invalid lock data"},"500":{"description":"An unknown error occurred"}},"summary":"Verify Distributed Validator Cluster Lock Data","tags":["Cluster Lock"]}},"/v1/state/{lockHash}":{"get":{"description":"This endpoint is used to retrieve the states of all validators in a DV Cluster","operationId":"StateController_getDistributedValidatorStatesByLockHash_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lock_hash` calculated for a cluster lock.","schema":{"type":"string"}}],"responses":{"200":{"description":"A map of pubkeys to DVState","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/DistributedValidatorStateResponse"}],"example":{"0x000000000000000000000000000000":{"index":"0","status":"active_ongoing","balance":"32"}}}}}},"400":{"description":"Bad request received"},"404":{"description":"Lock Hash not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve the Validator states for a cluster","tags":["State"]}},"/exp/exit/status/summary/{lockHash}":{"get":{"description":"It shows data of operators who have signed and the count of validators ready to exit","operationId":"ExitController_getClusterExitStatusSummary[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lock hash.","schema":{"type":"string"}}],"responses":{"200":{"description":"The exit summary data","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterExitStatusSummaryResponse"}]}}}},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve validators exit status summary","tags":["DV Exit"]}},"/v1/exp/exit/status/summary/{lockHash}":{"get":{"description":"It shows data of operators who have signed and the count of validators ready to exit","operationId":"ExitController_getClusterExitStatusSummary[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lock hash.","schema":{"type":"string"}}],"responses":{"200":{"description":"The exit summary data","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterExitStatusSummaryResponse"}]}}}},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve validators exit status summary","tags":["DV Exit"]}},"/exp/exit/status/{lockHash}":{"get":{"description":"It shows data of operators who have signed and who have not","operationId":"ExitController_getClusterExitStatus[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lockHash.","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"type":"number"}},{"name":"operatorAddress","required":true,"in":"query","description":"The operatorAddress.","schema":{"type":"string"}},{"name":"validatorPubkey","required":true,"in":"query","description":"The `pubkey` in a cluster lock.","schema":{"type":"string"}}],"responses":{"200":{"description":"The exit status data","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterExitStatusResponse"}]}}}},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve validators exit status","tags":["DV Exit"]}},"/v1/exp/exit/status/{lockHash}":{"get":{"description":"It shows data of operators who have signed and who have not","operationId":"ExitController_getClusterExitStatus[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lockHash.","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"type":"number"}},{"name":"operatorAddress","required":true,"in":"query","description":"The operatorAddress.","schema":{"type":"string"}},{"name":"validatorPubkey","required":true,"in":"query","description":"The `pubkey` in a cluster lock.","schema":{"type":"string"}}],"responses":{"200":{"description":"The exit status data","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterExitStatusResponse"}]}}}},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve validators exit status","tags":["DV Exit"]}},"/exp/exit/{lockHash}/{shareIdx}/{validatorPubkey}":{"get":{"description":"This endpoint is used to retrieve validator exit message","operationId":"ExitController_getClusterExit[0]","parameters":[{"name":"validatorPubkey","required":true,"in":"path","description":"The `distributed_public_key` in a cluster lock.","schema":{"type":"string"}},{"name":"shareIdx","required":true,"in":"path","description":"Represents the cluster operatorIndex+1.","schema":{}},{"name":"lockHash","required":true,"in":"path","description":"The cluster lockHash.","schema":{}}],"responses":{"200":{"description":"The DV signed exit message","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ExitBlob"}]}}}},"401":{"description":"Authorization header is missing or incorrect"},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Retrieve Distributed Validator threshold aggregated signed exit msg","tags":["DV Exit"]}},"/v1/exp/exit/{lockHash}/{shareIdx}/{validatorPubkey}":{"get":{"description":"This endpoint is used to retrieve validator exit message","operationId":"ExitController_getClusterExit[1]_v1","parameters":[{"name":"validatorPubkey","required":true,"in":"path","description":"The `distributed_public_key` in a cluster lock.","schema":{"type":"string"}},{"name":"shareIdx","required":true,"in":"path","description":"Represents the cluster operatorIndex+1.","schema":{}},{"name":"lockHash","required":true,"in":"path","description":"The cluster lockHash.","schema":{}}],"responses":{"200":{"description":"The DV signed exit message","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ExitBlob"}]}}}},"401":{"description":"Authorization header is missing or incorrect"},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Retrieve Distributed Validator threshold aggregated signed exit msg","tags":["DV Exit"]}},"/exp/partial_exits/{lockHash}":{"post":{"description":"This endpoint saves partial signed exit messages.","operationId":"ExitController_postPartialExit[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lockHash` of the cluster which the validator belongs to","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExitDto"}}}},"responses":{"201":{"description":"success message"},"400":{"description":"Bad request received"},"404":{"description":"Data or validator not found"},"409":{"description":"Duplicate entry"},"500":{"description":"An unknown error occurred"}},"summary":"Push Distributed Validator partial signed exit message","tags":["DV Exit"]}},"/v1/exp/partial_exits/{lockHash}":{"post":{"description":"This endpoint saves partial signed exit messages.","operationId":"ExitController_postPartialExit[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lockHash` of the cluster which the validator belongs to","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExitDto"}}}},"responses":{"201":{"description":"success message"},"400":{"description":"Bad request received"},"404":{"description":"Data or validator not found"},"409":{"description":"Duplicate entry"},"500":{"description":"An unknown error occurred"}},"summary":"Push Distributed Validator partial signed exit message","tags":["DV Exit"]}},"/v1/effectiveness/{lockHash}":{"get":{"description":"This endpoint is used to retrieve the effectiveness of a cluster by pubkey","operationId":"EffectivenessController_getClusterLock_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The `lock_hash` calculated for a cluster lock.","schema":{"type":"string"}}],"responses":{"200":{"description":"The cluster lock object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClusterEffectivenessResponse"}]}}}},"404":{"description":"Data not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a Distributed Validator Cluster Effectiveness Object","tags":["Cluster Effectiveness"]}},"/v1/termsAndConditions":{"post":{"description":"Saves user's signature to latest [Obol's terms and conditions](https://obol.tech/terms.pdf) hash and it's version","operationId":"TermsAndConditionsController_signTermsAndConditions_v1","parameters":[{"name":"authorization","required":true,"in":"header","description":"EIP712 terms and conditions hash as bearer token","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TermsAndConditionsDto"}}}},"responses":{"201":{"description":"success message"},"400":{"description":"Invalid terms and conditions hash"},"401":{"description":"Signature verification failed"},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Saves user's approval latest terms and conditions","tags":["Terms And Conditions"]}},"/v1/termsAndConditions/{address}":{"get":{"description":"This endpoint is used to check whether the Terms and Conditions has been signed by the user.","operationId":"TermsAndConditionsController_getTermsAndConditionsSigned_v1","parameters":[{"name":"address","required":true,"in":"path","description":"The address to check the Terms and Conditions.","schema":{"type":"string"}}],"responses":{"200":{"description":"This value returns true if the Terms and Conditions have been signed; otherwise, it returns false.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TermsAndConditions"}]}}}},"400":{"description":"The Address provided is not valid"},"500":{"description":"An unknown error occurred"}},"summary":"Verify Signature on Terms and Conditions","tags":["Terms And Conditions"]}},"/v1/techne/base/{index}":{"get":{"description":"This endpoint is used to retrieve Base techne credential metadata","operationId":"TechneController_getBaseCred_v1","parameters":[{"name":"index","required":true,"in":"path","description":"The techne index.","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TechneResponse"}}}},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Retrieve Base techne credential metadata","tags":["Techne Credentials"]}},"/v1/techne/bronze/{index}":{"get":{"description":"This endpoint is used to retrieve Bronze techne credential metadata","operationId":"TechneController_getBronzeCred_v1","parameters":[{"name":"index","required":true,"in":"path","description":"The techne index.","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TechneResponse"}}}},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Retrieve Bronze techne credential metadata","tags":["Techne Credentials"]}},"/v1/techne/silver/{index}":{"get":{"description":"This endpoint is used to retrieve Silver techne credential metadata","operationId":"TechneController_getSilverCred_v1","parameters":[{"name":"index","required":true,"in":"path","description":"The techne index.","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TechneResponse"}}}},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Retrieve Silver techne credential metadata","tags":["Techne Credentials"]}},"/v1/techne/gold/{index}":{"get":{"description":"This endpoint is used to retrieve Gold techne credential metadata","operationId":"TechneController_getGoldCred_v1","parameters":[{"name":"index","required":true,"in":"path","description":"The techne index.","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TechneResponse"}}}},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Retrieve Gold techne credential metadata","tags":["Techne Credentials"]}},"/v1/address/techne/{address}":{"get":{"description":"This endpoint is used to retrieve obol techne credentials an address owns","operationId":"AddressController_getAddressTechneCredentials_v1","parameters":[{"name":"address","required":true,"in":"path","description":"The address to check the techne credentials for.","schema":{"type":"string"}}],"responses":{"200":{"description":"The address techne credentials object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AddressTechneResponse"}]}}}},"400":{"description":"The Address provided is not valid"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve obol techne credentials of an address","tags":["Address"]}},"/v1/address/badges/{address}":{"get":{"description":"This endpoint is used to retrieve the badges an address owns","operationId":"AddressController_getAddressBadgess_v1","parameters":[{"name":"address","required":true,"in":"path","description":"The address to check the techne credentials for.","schema":{"type":"string"}}],"responses":{"200":{"description":"The address techne credentials object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AddressBadgeResponse"}]}}}},"400":{"description":"The Address provided is not valid"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve badges for an address","tags":["Address"]}},"/v1/address/incentives/{network}/{address}":{"get":{"description":"This endpoint is used to retrieve incentives an address owns","operationId":"AddressController_getAddressIncentives_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve operators on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"address","required":true,"in":"path","description":"The address to check the incentives for.","schema":{"type":"string"}}],"responses":{"200":{"description":"The address incentives object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AddressIncentivesResponse"}]}}}},"400":{"description":"The Address provided is not valid"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve obol incentives of an address","tags":["Address"]}},"/v1/address/incentives/historical/{network}/{address}":{"get":{"description":"This endpoint is used to retrieve the inventives given to Obol Public Goods by an address.","operationId":"AddressController_getHistoricalAddressContributions_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve operators on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"address","required":true,"in":"path","description":"The address to check the incentives for.","schema":{"type":"string"}},{"name":"date","required":true,"in":"query","schema":{"format":"date-time","type":"string"}}],"responses":{"200":{"description":"The address contributions object","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AddressIncentivesResponse"}]}}}},"400":{"description":"The Address provided is not valid"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve the historical incentives of an address","tags":["Address"]}},"/v1/address/network/{network}":{"get":{"description":"This endpoint fetches a number of operators for a given network.","operationId":"AddressController_getOperatorsByNetwork_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve operators on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"limit","required":true,"in":"query","description":"The number of operators to return.","schema":{"type":"integer","default":100}},{"name":"sortBy","required":false,"in":"query","description":"numerical field to sort by","schema":{"type":"string","default":"active_validators_count"}},{"name":"sortOrder","required":false,"in":"query","description":"order of sorting the field","schema":{"type":"string","default":"desc"}},{"name":"techne","required":false,"in":"query","description":"techne to filter by","schema":{"type":"object","properties":{"bronze":{"type":"boolean"},"silver":{"type":"boolean"}}}},{"name":"badges","required":false,"in":"query","description":"badges to filter by","schema":{"type":"object","properties":{"lido":{"type":"boolean"},"etherfi":{"type":"boolean"}}}},{"name":"details","required":true,"in":"query","description":"The flag to populate operators information.","schema":{"type":"string","default":"false"}}],"responses":{"200":{"description":"A paged list of Operators on this network","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/OperatorsPagedResponse"}]}}}},"400":{"description":"Network not spported"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve operators on a given network","tags":["Address"]}},"/v1/address/search/{network}":{"get":{"description":"This endpoint is used to search for operators that match a substring of their `address`.","operationId":"AddressController_searchOperators_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve operators on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"partialAddress","required":true,"in":"query","description":"A substring of the `address` of Operator.","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"limit","required":true,"in":"query","description":"The number of operators to return.","schema":{"type":"integer","default":100}}],"responses":{"200":{"description":"A paged list of Operators on this network","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/OperatorsPagedResponse"}]}}}},"404":{"description":"Operators not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve a list operators on a given network","tags":["Address"]}},"/v1/address/migrateable-validators/{network}/{withdrawalAddress}":{"get":{"description":"This endpoint is used fetch eligible validators for migration .","operationId":"AddressController_getMigrateableValidators_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve active validators on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"withdrawalAddress","required":true,"in":"path","description":"Withdrawal address of source validators.","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","description":"The number of validators to return.","schema":{"type":"integer","default":50}},{"name":"offset","required":true,"in":"query","description":"The number of items to skip before starting to collect the result set","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"A list of source validators the withdrawal address can migrate","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MigrateableValidatorsResponse"}]}}}},"400":{"description":"Beaconchain error"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve migrateable validators for withdrawal address","tags":["Address"]}},"/v1/owr/{network}/{address}":{"get":{"description":"This endpoint is used to retrieve information on the tranches of an OWR.","operationId":"OWRController_get_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network of the OWR.","schema":{"type":"string"}},{"name":"address","required":true,"in":"path","description":"The address of the OWR.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OWRResponse"}}}},"500":{"description":"An unknown error occurred"}},"security":[{"bearer":[]}],"summary":"Retrieve OWR tranch information","tags":["OWR Information"]}},"/v1/migrate/{network}":{"get":{"description":"It shows data of validators status","operationId":"MigrateController_getValidatorsMigrateStatus_v1","parameters":[{"name":"network","required":true,"in":"path","description":"The network to retrieve clusters on","examples":{"mainnet":{"summary":"Ethereum Mainnet","value":"mainnet"},"holesky":{"summary":"Holesky Test Network","value":"holesky"},"sepolia":{"summary":"Sepolia Test Network","value":"sepolia"}},"schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","description":"The number of validators to return.","schema":{"type":"integer","default":50}},{"name":"page","required":true,"in":"query","description":"The page number to retrieve.","schema":{"type":"integer","default":0}},{"name":"withdrawalAddress","required":true,"in":"query","description":"Withdrawal address of target validators.","schema":{"type":"string"}},{"name":"targetPubKey","required":true,"in":"query","description":"The `pubkey` of target validator.","schema":{"type":"string"}}],"responses":{"200":{"description":"The migration status data","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MigrationStateResponse"}]}}}},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve validators migrate status","tags":["DV Migrate"]}},"/v1/test":{"post":{"description":"This endpoint saves test result data to the database.","operationId":"TestController_postTestResult_v1","parameters":[{"name":"Authorization","in":"header","description":"Bearer token containing the signature","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestResultDto"}}}},"responses":{"201":{"description":"Test result data stored successfully"},"400":{"description":"Invalid test result data"},"401":{"description":"Unauthorized - Signature verification failed"},"500":{"description":"An unknown error occurred"}},"summary":"Store test result data","tags":["Test"]}},"/v1/test/enr/{enr}":{"get":{"description":"This endpoint retrieves test results for a specific ENR.","operationId":"TestController_getTestResultByEnr_v1","parameters":[{"name":"enr","required":true,"in":"path","description":"ENR to search for","schema":{"type":"string"}}],"responses":{"200":{"description":"Test results found","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestResultDto"}}}}},"404":{"description":"No test results found for this ENR"},"500":{"description":"An unknown error occurred"}},"summary":"Get test results by ENR","tags":["Test"]}},"/deposit_data/{lockHash}/{pubkey}":{"get":{"description":"This endpoint returns all partial deposit data grouped by amount for a specific validator","operationId":"DepositController_getDeposits[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lock hash","schema":{"type":"string"}},{"name":"pubkey","required":true,"in":"path","description":"The validator public key (distributed_public_key)","schema":{"type":"string"}}],"responses":{"200":{"description":"The deposit data","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/DepositDataResponse"}]}}}},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve partial deposit data for a validator","tags":["Deposit Data"]}},"/v1/deposit_data/{lockHash}/{pubkey}":{"get":{"description":"This endpoint returns all partial deposit data grouped by amount for a specific validator","operationId":"DepositController_getDeposits[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lock hash","schema":{"type":"string"}},{"name":"pubkey","required":true,"in":"path","description":"The validator public key (distributed_public_key)","schema":{"type":"string"}}],"responses":{"200":{"description":"The deposit data","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/DepositDataResponse"}]}}}},"404":{"description":"Data is not found"},"500":{"description":"An unknown error occurred"}},"summary":"Retrieve partial deposit data for a validator","tags":["Deposit Data"]}},"/deposit_data/partial_deposits/{lockHash}/{share_index}":{"post":{"description":"This endpoint saves partial deposit data signed by an operator","operationId":"DepositController_submitPartialDeposits[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The lock hash of the cluster","schema":{"type":"string"}},{"name":"share_index","required":true,"in":"path","description":"The share index (operator index + 1)","schema":{"type":"number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepositDto"}}}},"responses":{"201":{"description":"Deposit data saved successfully"},"400":{"description":"Invalid request format | Conflicting withdrawal address. Delete the existing deposits first. | Validator is already initialised."},"401":{"description":"Invalid deposit signature"},"404":{"description":"Data or validator not found"},"500":{"description":"An unknown error occurred"}},"summary":"Push partial deposit data","tags":["Deposit Data"]}},"/v1/deposit_data/partial_deposits/{lockHash}/{share_index}":{"post":{"description":"This endpoint saves partial deposit data signed by an operator","operationId":"DepositController_submitPartialDeposits[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The lock hash of the cluster","schema":{"type":"string"}},{"name":"share_index","required":true,"in":"path","description":"The share index (operator index + 1)","schema":{"type":"number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepositDto"}}}},"responses":{"201":{"description":"Deposit data saved successfully"},"400":{"description":"Invalid request format | Conflicting withdrawal address. Delete the existing deposits first. | Validator is already initialised."},"401":{"description":"Invalid deposit signature"},"404":{"description":"Data or validator not found"},"500":{"description":"An unknown error occurred"}},"summary":"Push partial deposit data","tags":["Deposit Data"]}},"/tvs/{network}":{"get":{"description":"Returns either summary (total balance) or detailed (validator-level) TVS data for a specific timestamp. All returned data (balances, counts, totals) corresponds to the timestamp shown in the response. Each network has one data snapshot per day.","operationId":"TVSController_getTVS[0]","parameters":[{"name":"network","required":true,"in":"path","description":"Network name (e.g., mainnet, hoodi)","schema":{"example":"mainnet","type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of results per page (only applies when details=true).","schema":{"type":"integer","default":100,"maximum":1000}},{"name":"page","required":false,"in":"query","description":"Page number (only applies when details=true)","schema":{"type":"integer","default":0}},{"name":"details","required":false,"in":"query","description":"If true, returns detailed validator-level data","schema":{"type":"string","default":"false"}},{"name":"timestamp","required":false,"in":"query","description":"ISO 8601 timestamp or date (YYYY-MM-DD). If date-only format is used, returns data for that day regardless of exact time. If not provided, returns the latest available data.","schema":{"example":"2025-10-02"}}],"responses":{"200":{"description":"TVS data retrieved successfully","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/TVSSummaryResponse"},{"$ref":"#/components/schemas/TVSDetailedResponse"}]}}}},"400":{"description":"Invalid parameters"},"404":{"description":"No data found for the specified network/timestamp"},"500":{"description":"An unknown error occurred"}},"summary":"Get Total Value Staked Of Obol for a network","tags":["tvs"]}},"/v1/tvs/{network}":{"get":{"description":"Returns either summary (total balance) or detailed (validator-level) TVS data for a specific timestamp. All returned data (balances, counts, totals) corresponds to the timestamp shown in the response. Each network has one data snapshot per day.","operationId":"TVSController_getTVS[1]_v1","parameters":[{"name":"network","required":true,"in":"path","description":"Network name (e.g., mainnet, hoodi)","schema":{"example":"mainnet","type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of results per page (only applies when details=true).","schema":{"type":"integer","default":100,"maximum":1000}},{"name":"page","required":false,"in":"query","description":"Page number (only applies when details=true)","schema":{"type":"integer","default":0}},{"name":"details","required":false,"in":"query","description":"If true, returns detailed validator-level data","schema":{"type":"string","default":"false"}},{"name":"timestamp","required":false,"in":"query","description":"ISO 8601 timestamp or date (YYYY-MM-DD). If date-only format is used, returns data for that day regardless of exact time. If not provided, returns the latest available data.","schema":{"example":"2025-10-02"}}],"responses":{"200":{"description":"TVS data retrieved successfully","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/TVSSummaryResponse"},{"$ref":"#/components/schemas/TVSDetailedResponse"}]}}}},"400":{"description":"Invalid parameters"},"404":{"description":"No data found for the specified network/timestamp"},"500":{"description":"An unknown error occurred"}},"summary":"Get Total Value Staked Of Obol for a network","tags":["tvs"]}}},"info":{"title":"Obol API","description":"## What is this API?\n\nThis API is for creating and managing [Distributed Validators](https://docs.obol.tech/docs/int/key-concepts#distributed-validator). This API works in tandem with Obol's [Distributed Validator Launchpad](https://holesky.launchpad.obol.org), a dapp designed to allow people to authenticate their counterparties and agree to the terms of a Distributed Validator Cluster. This API will be made more easy for code-only interaction in the coming quarters with the release of the Obol-SDK. \n\nRead more about Obol and how to use the [launchpad](https://holesky.launchpad.obol.org) on our [docs site](https://docs.obol.tech/). \n\nFor enquiries:","version":"v1.0.0-local","contact":{"name":"Obol Labs","url":"https://obol.tech","email":"support@obol.tech"}},"tags":[{"name":"Distributed Validators","description":"Configuration for distributed validator key generation ceremonies."},{"name":"System","description":"System related endpoints."}],"servers":[{"url":"https://api.obol.tech","description":"Production environment"},{"url":"http://localhost:3000","description":"Local development server"},{"url":"https://localhost:3000","description":"HTTPS Local development server"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"Creator":{"type":"object","properties":{}},"Validator":{"type":"object","properties":{}},"Operator":{"type":"object","properties":{}},"ClusterDefinitionResponse":{"type":"object","properties":{"name":{"type":"string","example":"My Obol Cluster"},"uuid":{"type":"string","example":"0194FDC2-FA2F-FCC0-41D3-FF12045B73C8"},"creator":{"$ref":"#/components/schemas/Creator"},"version":{"type":"string","example":"v1.8.0"},"num_validators":{"type":"number","example":5},"threshold":{"type":"number","example":3},"dkg_algorithm":{"type":"string","example":"default"},"fork_version":{"type":"string","example":"0x00001020"},"config_hash":{"type":"string","description":"config_hash is a 32 bytes SSZ hash of cluster config.","example":"0x2204ba6c238ed2d6a8ff951d4513db993c8d6f8860468391342649bf735a87d7"},"timestamp":{"type":"string","example":"2022-07-19T18:19:58+02:00"},"validators":{"type":"array","items":{"$ref":"#/components/schemas/Validator"}},"deposit_amounts":{"description":"Partial depoists.","example":["8000000000","16000000000","8000000000"],"type":"array","items":{"type":"string"}},"definition_hash":{"type":"string","description":"definition_hash is a 32 bytes SSZ hash of cluster config.","example":"0xb656f5a4a5537b5817d6bcf735d043f17f5aff568b1a7ec9102a9f687bd4510c"},"fee_recipient_address":{"type":"string","description":"Ethereum address to receive transaction fees.","example":"0x000000000000000000000000000000000000dead"},"withdrawal_address":{"type":"string","description":"Ethereum address to receive staked ether.","example":"0x000000000000000000000000000000000000dead"},"operators":{"type":"array","items":{"$ref":"#/components/schemas/Operator"}},"consensus_protocol":{"type":"string","example":"qbft"},"target_gas_limit":{"type":"number","example":36000000},"compounding":{"type":"boolean","example":true}},"required":["name","uuid","creator","version","num_validators","threshold","dkg_algorithm","fork_version","config_hash","timestamp","validators","deposit_amounts","definition_hash","fee_recipient_address","withdrawal_address","operators","consensus_protocol","target_gas_limit","compounding"]},"ClusterDefinitionPagedResponse":{"type":"object","properties":{"cluster_definitions":{"type":"array","items":{"$ref":"#/components/schemas/ClusterDefinitionResponse"}},"total_count":{"type":"number","example":2},"total_pages":{"type":"number","example":3}},"required":["cluster_definitions","total_count","total_pages"]},"OperatorDto":{"type":"object","properties":{"address":{"type":"string","description":"Ethereum address of Operator.","example":"0x000000000000000000000000000000000000dead"},"enr":{"type":"string","example":"enr://5fb90badb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c848621"},"fork_version":{"type":"string","enum":["mainnet","0x00000000","goerli","0x00001020","gnosis","0x00000064","sepolia","0x90000069","holesky","0x01017000","hoodi","0x10000910"],"example":"0x00001020"},"version":{"type":"string","example":"v1.8.0"},"enr_signature":{"type":"string","example":"0x1199fc4440aa7929905ec171ed1dad82a9f6a89891193b2b4cf45937a8cf9ece4972e02bc7e23d8b8b2e550b6430693ac6bc8c82a0509f65d0abb34d7ae0a8a81c"},"config_signature":{"type":"string","example":"0x1199fc4440aa7929905ec171ed1dad82a9f6a89891193b2b4cf45937a8cf9ece4972e02bc7e23d8b8b2e550b6430693ac6bc8c82a0509f65d0abb34d7ae0a8a81c"}},"required":["address","enr","fork_version","version","enr_signature","config_signature"]},"CreatorDto":{"type":"object","properties":{"address":{"type":"string","description":"Ethereum address of Creator.","example":"0x000000000000000000000000000000000000dead"},"config_signature":{"type":"string","example":"0x1199fc4440aa7929905ec171ed1dad82a9f6a89891193b2b4cf45937a8cf9ece4972e02bc7e23d8b8b2e550b6430693ac6bc8c82a0509f65d0abb34d7ae0a8a81c"}},"required":["address","config_signature"]},"ClusterDefValidator":{"type":"object","properties":{"fee_recipient_address":{"type":"string","description":"Ethereum address to receive transaction fees.","example":"0x000000000000000000000000000000000000dead"},"withdrawal_address":{"type":"string","description":"Ethereum address to receive staked ether.","example":"0x000000000000000000000000000000000000dead"}},"required":["fee_recipient_address","withdrawal_address"]},"ClusterDefDto":{"type":"object","properties":{"name":{"type":"string","example":"My Obol Cluster"},"operators":{"minItems":3,"description":"operator data.","type":"array","items":{"$ref":"#/components/schemas/OperatorDto"}},"creator":{"description":"creator data.","type":"array","items":{"$ref":"#/components/schemas/CreatorDto"}},"uuid":{"type":"string","example":"0194FDC2-FA2F-FCC0-41D3-FF12045B73C8"},"version":{"type":"string","example":"v1.8.0"},"num_validators":{"type":"number","minimum":1,"example":5},"threshold":{"type":"number","minimum":1,"example":3},"dkg_algorithm":{"type":"string","enum":["frost","keycast","default"],"example":"default"},"fork_version":{"type":"string","enum":["mainnet","0x00000000","goerli","0x00001020","gnosis","0x00000064","sepolia","0x90000069","holesky","0x01017000","hoodi","0x10000910"],"example":"0x00001020"},"timestamp":{"type":"string","example":"2022-07-19T18:19:58+02:00"},"validators":{"description":"validator withdrawal configuration.","type":"array","items":{"$ref":"#/components/schemas/ClusterDefValidator"}},"deposit_amounts":{"description":"partial deposits.","type":"array","items":{"type":"string"}},"consensus_protocol":{"type":"string","enum":["qbft",""],"example":"qbft"},"target_gas_limit":{"type":"number","minimum":1,"example":36000000},"compounding":{"type":"boolean","description":"Flag that enables compounding rewards for validators by using 0x02 withdrawal credentials"},"config_hash":{"type":"string","example":"0x29b0223beea5f4f74391f445d15afd4294040374f6924b98cbf8713f8d962d7c"}},"required":["name","operators","creator","uuid","version","num_validators","threshold","dkg_algorithm","fork_version","timestamp","validators","deposit_amounts","consensus_protocol","target_gas_limit","compounding","config_hash"]},"DistributedValidator":{"type":"object","properties":{}},"ClusterLockResponse":{"type":"object","properties":{"cluster_definition":{"description":"Cluster definition data that was used in dkg to generate cluster lock.","allOf":[{"$ref":"#/components/schemas/ClusterDefinitionResponse"}]},"distributed_validators":{"type":"array","items":{"$ref":"#/components/schemas/DistributedValidator"}},"signature_aggregate":{"type":"string","example":"0x85650c30ec29a3703934bf50a28da102975deda77e758579ea3dfe4136abf752"},"lock_hash":{"type":"string","example":"0xd2880980169ee4a0000f23feb8fad9a6c70f38312956fe67aa89e118f5b0e048"},"node_signatures":{"type":"array","items":{"type":"string"}}},"required":["cluster_definition","distributed_validators","signature_aggregate","lock_hash","node_signatures"]},"ClusterLockPagedResponse":{"type":"object","properties":{"cluster_locks":{"type":"array","items":{"type":"string"}},"total_active_stake_eth":{"type":"number","example":128.5},"total_active_stake_usd":{"type":"number","example":128.5},"total_count":{"type":"number","example":2},"total_pages":{"type":"number","example":4}},"required":["cluster_locks","total_count","total_pages"]},"ClusterLockNetworkSummaryResponse":{"type":"object","properties":{"eth_staked":{"type":"number","example":2},"total_clusters":{"type":"number","example":2},"total_operators":{"type":"number","example":4}},"required":["eth_staked","total_clusters","total_operators"]},"DepositDataDto":{"type":"object","properties":{"pubkey":{"type":"string","pattern":"^(0x|0h)?[0-9A-F]+$","example":"0xb51336c31c4f0cc365d6c7b5d8ff1b4b7d4cf7c70163f9fd51a2badc854f5e29823fa11e3d7749d207807867149508d6"},"withdrawal_credentials":{"type":"string","example":"0x01000000000000000000000086b8145c98e5bd25ba722645b15ed65f024a87ec"},"amount":{"type":"string","example":"32000000000"},"deposit_data_root":{"type":"string","example":"5e58a5d8f1e53479343cb6188f061f6b1a46c521c53eef0580b04f485ad62bad"},"signature":{"type":"string","example":"0x88fe84889608a8b2424bddae2047d2ee4b42f72c4d8201d69e732d7c3bfa1bcb00f930979770b7d00071673fde8f205108dabe8d83ec49aa6de1b7869966b555be80a159e6ad11e273c4e0234038cfa525923044d6a89a4924fdc178f333568b"}},"required":["pubkey","withdrawal_credentials","amount","deposit_data_root","signature"]},"BuilderRegistrationMessageDto":{"type":"object","properties":{"fee_recipient":{"type":"string","example":"0x86B8145c98e5BD25BA722645b15eD65f024a87EC"},"gas_limit":{"type":"number","example":30000000},"timestamp":{"type":"number","example":1616508000},"pubkey":{"type":"string","pattern":"^(0x|0h)?[0-9A-F]+$","example":"0xb51336c31c4f0cc365d6c7b5d8ff1b4b7d4cf7c70163f9fd51a2badc854f5e29823fa11e3d7749d207807867149508d6"}},"required":["fee_recipient","gas_limit","timestamp","pubkey"]},"BuilderRegistrationDto":{"type":"object","properties":{"message":{"description":"builder registration information.","allOf":[{"$ref":"#/components/schemas/BuilderRegistrationMessageDto"}]},"signature":{"type":"string","example":"0x851e4f196b7e7bda6429b94cceb92d480f53fa9753e1d6c830ff2706acb8cd866d81d5533db7dcfac1dc9d00a16e5e4801d33f36bdf1c2a2003e1c586466109e7851c79179b2c46d69c53c4a59e361d2727186a7e72bbd11debad1f2fae6f97d"}},"required":["message","signature"]},"DistributedValidatorDto":{"type":"object","properties":{"distributed_public_key":{"type":"string","pattern":"^(0x|0h)?[0-9A-F]+$","example":"0xb51336c31c4f0cc365d6c7b5d8ff1b4b7d4cf7c70163f9fd51a2badc854f5e29823fa11e3d7749d207807867149508d6"},"public_shares":{"description":"array of public shares of the distributed public key.","type":"array","items":{"type":"string","pattern":"^(0x|0h)?[0-9A-F]+$"}},"deposit_data":{"description":"Deposit data for validator activation.","allOf":[{"$ref":"#/components/schemas/DepositDataDto"}]},"builder_registration":{"description":"Pre-generated signed validator builder registration.","allOf":[{"$ref":"#/components/schemas/BuilderRegistrationDto"}]},"partial_deposit_data":{"description":"Deposit data for validator activation.","allOf":[{"$ref":"#/components/schemas/DepositDataDto"}]}},"required":["distributed_public_key","public_shares","deposit_data","builder_registration","partial_deposit_data"]},"ClusterLockDto":{"type":"object","properties":{"cluster_definition":{"description":"Cluster definition data that was used in dkg to generate cluster lock.","allOf":[{"$ref":"#/components/schemas/ClusterDefinitionResponse"}]},"distributed_validators":{"description":"distributed validator keys and deposit data.","type":"array","items":{"$ref":"#/components/schemas/DistributedValidatorDto"}},"signature_aggregate":{"type":"string","example":"0x85650c30ec29a3703934bf50a28da102975deda77e758579ea3dfe4136abf752"},"lock_hash":{"type":"string","example":"0xd2880980169ee4a0000f23feb8fad9a6c70f38312956fe67aa89e118f5b0e048"},"node_signatures":{"example":["0xe6e531be7bbf6cee37d80ab489ade6491469e10743d3c1496a3e66fe989eb4c100c260eaee4ef1aa08fdb79ea05bb8c12970dec1a296abe627ac25a2515373b301"],"type":"array","items":{"type":"string","pattern":"^(0x|0h)?[0-9A-F]+$"}}},"required":["cluster_definition","distributed_validators","signature_aggregate","lock_hash","node_signatures"]},"DistributedValidatorStateResponse":{"type":"object","properties":{"index":{"type":"string","example":"12345"},"status":{"type":"string","example":"active_ongoing"},"balance":{"type":"string","example":"32"},"effective_balance":{"type":"string","example":"32"},"withdrawal_credentials":{"type":"string","example":"0x01000000000000000000000086b8145c98e5bd25ba722645b15ed65f024a87ec"},"pending_partial_withdrawals":{"type":"string","example":"3"},"pending_partial_deposits":{"type":"string","example":"3"},"is_not_within_committee":{"type":"boolean","example":true,"description":"Indicates if validator has been active for at least 256 epochs and is not within the committee period"}},"required":["index","status","balance","effective_balance","withdrawal_credentials","pending_partial_withdrawals","pending_partial_deposits","is_not_within_committee"]},"ClusterExitStatusSummaryResponse":{"type":"object","properties":{"operator_exits":{"type":"object","example":{"0x000000000000000000000000000000000000dea1":5,"0x000000000000000000000000000000000000dead":10},"description":"An object where the key is an operator address and the value is a number of signed validators."},"ready_exits":{"type":"number","example":2}},"required":["operator_exits","ready_exits"]},"ClusterExitStatusResponse":{"type":"object","properties":{}},"ExitBlob":{"type":"object","properties":{}},"ExitMessageDto":{"type":"object","properties":{"epoch":{"type":"string","example":"162304"},"validator_index":{"type":"string","example":"42"}},"required":["epoch","validator_index"]},"SignedExitMessageDto":{"type":"object","properties":{"message":{"$ref":"#/components/schemas/ExitMessageDto"},"signature":{"type":"string","example":""}},"required":["message","signature"]},"ExitBlobDto":{"type":"object","properties":{"public_key":{"type":"string","pattern":"^(0x|0h)?[0-9A-F]+$","example":"0x8b69c67720c909423d7edc5d3a7554e1d1e50f6d7d5f8d18548d68daf424e536afba8b31fbd15df1970ba4af4a7d944c"},"signed_exit_message":{"$ref":"#/components/schemas/SignedExitMessageDto"}},"required":["public_key","signed_exit_message"]},"ExitDto":{"type":"object","properties":{"partial_exits":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/ExitBlobDto"}},"share_idx":{"type":"number","example":42},"signature":{"type":"string","example":""}},"required":["partial_exits","share_idx","signature"]},"ClusterEffectivenessResponse":{"type":"object","properties":{"oneDay":{"type":"number","description":"Cluster effectiveness for the previous day."},"sevenDay":{"type":"number","description":"Cluster effectiveness for the previous 7 days."},"thirtyDay":{"type":"number","description":"Cluster effectiveness for the previous 30 days."},"all":{"type":"number","description":"Cluster effectiveness for alltime."}},"required":["oneDay","sevenDay","thirtyDay","all"]},"TermsAndConditionsDto":{"type":"object","properties":{"address":{"type":"string","example":"v1.0.0"},"version":{"type":"number","example":1},"terms_and_conditions_hash":{"type":"string","example":""},"fork_version":{"type":"string","enum":["mainnet","0x00000000","goerli","0x00001020","gnosis","0x00000064","sepolia","0x90000069","holesky","0x01017000","hoodi","0x10000910"],"example":"0x00000000"}},"required":["address","version","terms_and_conditions_hash"]},"TermsAndConditions":{"type":"object","properties":{"isTermsAndConditionsSigned":{"type":"boolean","description":"Boolean Value Indicating if Terms and Conditions Have Been Signed"}},"required":["isTermsAndConditionsSigned"]},"TechneResponse":{"type":"object","properties":{"description":{"type":"string","example":"Obol Techne Bronze Credential"},"external_url":{"type":"string","example":"https://blog.obol.tech/introducing-the-obol-techne-credential/"},"image":{"type":"string","example":"https://obol.tech/techne/bronze.png"},"name":{"type":"string","example":"Obol Techne - Bronze"}},"required":["description","external_url","image","name"]},"AddressTechneResponse":{"type":"object","properties":{"base":{"description":"","type":"array","items":{"type":"string"}},"bronze":{"description":"","type":"array","items":{"type":"string"}},"silver":{"description":"","type":"array","items":{"type":"string"}},"gold":{"description":"","type":"array","items":{"type":"string"}}},"required":["base","bronze","silver","gold"]},"AddressBadgeResponse":{"type":"object","properties":{"badges":{"description":"List of badge metadata","type":"array","items":{"type":"string"}}},"required":["badges"]},"AddressIncentivesResponse":{"type":"object","properties":{"operator_address":{"type":"string","description":"Operator address"},"amount":{"type":"string","description":"The amount the recipient is entitled to"},"index":{"type":"number","description":"The recipient’s index in the Merkle tree"},"merkle_proof":{"description":"The Merkle proof (an array of hashes) generated for the recipient","type":"array","items":{"type":"string"}},"contract_address":{"type":"string","description":"The MerkleDistributor contract address."}},"required":["operator_address","amount","index","merkle_proof","contract_address"]},"OperatorsPagedResponse":{"type":"object","properties":{"operators":{"type":"array","items":{"type":"string"}},"total_count":{"type":"number","example":2},"total_pages":{"type":"number","example":4}},"required":["operators","total_count","total_pages"]},"MigrateableValidatorsResponse":{"type":"object","properties":{"validators":{"type":"array","items":{"type":"string"}},"hasMore":{"type":"boolean"}},"required":["validators","hasMore"]},"OWRResponse":{"type":"object","properties":{"reward_recipient":{"type":"string","example":"0xA"},"principal_recipient":{"type":"string","example":"0xA"},"threshold":{"type":"string","example":"32000000000000000000"}},"required":["reward_recipient","principal_recipient","threshold"]},"ValidatorDetails":{"type":"object","properties":{"pubkey":{"type":"string","example":"12345"},"status":{"type":"string","example":"fully_migrated"},"effective_balance":{"type":"string","example":"32000000000","description":"Effective balance in gwei"},"lock_hash":{"type":"string","example":"0xd2880980169ee4a0000f23feb8fad9a6c70f38312956fe67aa89e118f5b0e048"}},"required":["pubkey","status","effective_balance","lock_hash"]},"MigrationStateResponse":{"type":"object","properties":{"validators":{"type":"array","items":{"$ref":"#/components/schemas/ValidatorDetails"}}},"required":["validators"]},"TestCategoryDto":{"type":"object","properties":{"category_name":{"type":"string","description":"Category name","example":"mev"},"execution_time":{"type":"string","description":"Execution time","example":"636.089125ms"},"score":{"type":"string","description":"Score letter grade","example":"A"},"targets":{"type":"object","description":"Targets with test results","example":{}}}},"TestResultDto":{"type":"object","properties":{"charon_peers":{"description":"Charon peers test results","allOf":[{"$ref":"#/components/schemas/TestCategoryDto"}]},"beacon_node":{"description":"Beacon node test results","allOf":[{"$ref":"#/components/schemas/TestCategoryDto"}]},"validator_client":{"description":"Validator client test results","allOf":[{"$ref":"#/components/schemas/TestCategoryDto"}]},"mev":{"description":"MEV test results","allOf":[{"$ref":"#/components/schemas/TestCategoryDto"}]},"infra":{"description":"Infrastructure test results","allOf":[{"$ref":"#/components/schemas/TestCategoryDto"}]},"enr":{"type":"string","description":"ENR value to verify against the signature","example":"enr://5fb90badb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c848621"},"sig":{"type":"string","description":"Signature from the ENR","example":"0x1234..."}}},"PartialDepositResponse":{"type":"object","properties":{"partial_public_key":{"type":"string","example":"0xPARTIAL_A","description":"Partial public key of the operator"},"partial_deposit_signature":{"type":"string","example":"0xSIG_A1","description":"Partial deposit signature"}},"required":["partial_public_key","partial_deposit_signature"]},"AmountGroupResponse":{"type":"object","properties":{"amount":{"type":"string","example":"32000000000","description":"Amount in Gwei"},"partials":{"description":"Array of partial deposits for this amount","type":"array","items":{"$ref":"#/components/schemas/PartialDepositResponse"}}},"required":["amount","partials"]},"DepositDataResponse":{"type":"object","properties":{"lock_hash":{"type":"string","example":"","description":""},"pubkey":{"type":"string","example":"0xFULL_1","description":"Full public key of the validator"},"withdrawal_credentials":{"type":"string","example":"0xWITHDRAW_1","description":"Withdrawal credentials"},"amounts":{"description":"Array of amounts with their partial deposits","type":"array","items":{"$ref":"#/components/schemas/AmountGroupResponse"}}},"required":["lock_hash","pubkey","withdrawal_credentials","amounts"]},"PartialDepositDataDto":{"type":"object","properties":{"pubkey":{"type":"string","pattern":"^(0x|0h)?[0-9A-F]+$","example":"0x8b69c67720c909423d7edc5d3a7554e1d1e50f6d7d5f8d18548d68daf424e536afba8b31fbd15df1970ba4af4a7d944c","description":"Public key of the validator (should be in lock file)"},"withdrawal_credentials":{"type":"string","example":"0x010000000000000000000000abcdef1234567890abcdef1234567890abcdef12","description":"Withdrawal credentials (0x01 or 0x02)"},"amount":{"type":"string","pattern":"/^\\d+$/","example":"32000000000","description":"Amount in Gwei as string (between 1 and 2048 ETH)"},"signature":{"type":"string","example":"0x1234...","description":"BLS signature over (pubkey, withdrawal_credentials, amount)"}},"required":["pubkey","withdrawal_credentials","amount","signature"]},"DepositDto":{"type":"object","properties":{"partial_deposit_data":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/PartialDepositDataDto"}}},"required":["partial_deposit_data"]},"TVSSummaryResponse":{"type":"object","properties":{"total_balance_eth":{"type":"number","description":"Total balance in ETH across all clusters at the specified timestamp (rounded to nearest integer)","example":12346},"total_balance_usd":{"type":"number","description":"Total balance in USD across all clusters at the specified timestamp (calculated using ETH closing price for that day, rounded to nearest integer)","example":45678901},"timestamp":{"type":"string","description":"Timestamp of the data snapshot. All data in this response is for this specific timestamp.","example":"2025-10-02T00:00:00.000Z"},"network":{"type":"string","description":"Network name","example":"mainnet"},"total_unclaimed_balance_eth_denominated":{"type":"number","description":"Total unclaimed balance in ETH (from daily fees/revenue data for the snapshot date)","example":67},"total_claimed_balance_eth_denominated":{"type":"number","description":"Total claimed balance in ETH (from daily fees/revenue data for the snapshot date)","example":71},"total_eth_transferred":{"type":"number","description":"Total ETH transferred (from daily fees/revenue data for the snapshot date)","example":4},"total_revenue":{"type":"number","description":"Total revenue (from daily fees/revenue data for the snapshot date)","example":142},"total_fees_eth_denominated":{"type":"number","description":"Total fees in ETH (from daily fees/revenue data for the snapshot date)","example":504}},"required":["total_balance_eth","total_balance_usd","timestamp","network"]},"ValidatorBalance":{"type":"object","properties":{"public_key":{"type":"string","description":"Validator public key","example":"0xa35873f8b87560432432b5247e0d88b23602db03695722585ac7e7151efd457f91fc5e8bd949b67777e5f1cfd504a902"},"balance_eth":{"type":"number","description":"Balance in ETH at the snapshot timestamp","example":32}},"required":["public_key","balance_eth"]},"TVSDetailedResponse":{"type":"object","properties":{"timestamp":{"type":"string","description":"Timestamp of the data snapshot. All data in this response (balances, counts) is for this specific timestamp.","example":"2025-10-02T00:00:00.000Z"},"network":{"type":"string","description":"Network name","example":"mainnet"},"balances":{"description":"Array of validator balances at the snapshot timestamp","type":"array","items":{"$ref":"#/components/schemas/ValidatorBalance"}},"total_count":{"type":"number","description":"Total number of validators at the snapshot timestamp (used for pagination)","example":100},"total_pages":{"type":"number","description":"Total number of pages based on the limit parameter and total_count at the snapshot timestamp","example":4}},"required":["timestamp","network","balances","total_count","total_pages"]}}}}