{"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"}},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"}},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"},"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"},"hoodi":{"summary":"Hoodi Test Network","value":"hoodi"},"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"]}},"/fee_recipient/partial/{lockHash}/{shareIdx}":{"post":{"description":"Stores partial BLS-signed builder registration messages for a given cluster operator. Partials are grouped into builder registrations by message content (fee_recipient, gas_limit, timestamp). The timestamp must be greater than or equal to the highest timestamp any operator has submitted for each pubkey. Equal timestamps are allowed so operators can join an existing registration group.","operationId":"FeeRecipientController_postPartialFeeRecipients[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lock hash.","schema":{"example":"0x1234abcd...","type":"string"}},{"name":"shareIdx","required":true,"in":"path","description":"The operator share index (1-based).","schema":{"example":1,"type":"number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeeRecipientDto"}}}},"responses":{"201":{"description":"Partial registrations saved successfully."},"400":{"description":"Invalid request body, signature verification failed, invalid share index, or duplicate pubkey in request."},"404":{"description":"Lock not found."},"500":{"description":"An unknown error occurred."}},"summary":"Submit partial fee recipient registrations","tags":["Fee Recipient"]}},"/v1/fee_recipient/partial/{lockHash}/{shareIdx}":{"post":{"description":"Stores partial BLS-signed builder registration messages for a given cluster operator. Partials are grouped into builder registrations by message content (fee_recipient, gas_limit, timestamp). The timestamp must be greater than or equal to the highest timestamp any operator has submitted for each pubkey. Equal timestamps are allowed so operators can join an existing registration group.","operationId":"FeeRecipientController_postPartialFeeRecipients[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lock hash.","schema":{"example":"0x1234abcd...","type":"string"}},{"name":"shareIdx","required":true,"in":"path","description":"The operator share index (1-based).","schema":{"example":1,"type":"number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeeRecipientDto"}}}},"responses":{"201":{"description":"Partial registrations saved successfully."},"400":{"description":"Invalid request body, signature verification failed, invalid share index, or duplicate pubkey in request."},"404":{"description":"Lock not found."},"500":{"description":"An unknown error occurred."}},"summary":"Submit partial fee recipient registrations","tags":["Fee Recipient"]}},"/fee_recipient/{lockHash}":{"post":{"description":"Returns builder registration status for validators in a cluster. For each validator, returns at most two registrations: the latest one that reached quorum (quorum: true) and the latest one still collecting signatures (quorum: false). Validators with no registration data are omitted. Optionally pass an array of pubkeys in the request body to filter results.","operationId":"FeeRecipientController_getPartialFeeRecipients[0]","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lock hash.","schema":{"example":"0x1234abcd...","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FetchQueryDto"}}}},"responses":{"200":{"description":"Per validator: at most 2 builder registrations (latest with quorum: true, latest with quorum: false). Each registration includes the signed message, partial signatures, and a quorum boolean. Pubkeys returned without 0x prefix."},"404":{"description":"Lock not found or no partial registrations found."},"500":{"description":"An unknown error occurred."}},"summary":"Fetch partial fee recipient registrations","tags":["Fee Recipient"]}},"/v1/fee_recipient/{lockHash}":{"post":{"description":"Returns builder registration status for validators in a cluster. For each validator, returns at most two registrations: the latest one that reached quorum (quorum: true) and the latest one still collecting signatures (quorum: false). Validators with no registration data are omitted. Optionally pass an array of pubkeys in the request body to filter results.","operationId":"FeeRecipientController_getPartialFeeRecipients[1]_v1","parameters":[{"name":"lockHash","required":true,"in":"path","description":"The cluster lock hash.","schema":{"example":"0x1234abcd...","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FetchQueryDto"}}}},"responses":{"200":{"description":"Per validator: at most 2 builder registrations (latest with quorum: true, latest with quorum: false). Each registration includes the signed message, partial signatures, and a quorum boolean. Pubkeys returned without 0x prefix."},"404":{"description":"Lock not found or no partial registrations found."},"500":{"description":"An unknown error occurred."}},"summary":"Fetch partial fee recipient registrations","tags":["Fee Recipient"]}},"/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"]}},"/positions/{network}/{address}":{"post":{"description":"Returns all DV clusters where the address (or any additional address) appears as withdrawal_address or fee_recipient. Also checks Lido protocol_fee_splitters.","operationId":"PositionsController_getPositions[0]","parameters":[{"name":"network","required":true,"in":"path","description":"Network name (mainnet, hoodi, etc.)","schema":{"type":"string"}},{"name":"address","required":true,"in":"path","description":"The address to look up positions for","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsRequestDto"}}}},"responses":{"200":{"description":"Positions found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsResponse"}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsResponse"}}}},"400":{"description":"Invalid network"},"500":{"description":"An unknown error occurred"}},"summary":"Get positions for an address","tags":["Positions"]}},"/v1/positions/{network}/{address}":{"post":{"description":"Returns all DV clusters where the address (or any additional address) appears as withdrawal_address or fee_recipient. Also checks Lido protocol_fee_splitters.","operationId":"PositionsController_getPositions[1]_v1","parameters":[{"name":"network","required":true,"in":"path","description":"Network name (mainnet, hoodi, etc.)","schema":{"type":"string"}},{"name":"address","required":true,"in":"path","description":"The address to look up positions for","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsRequestDto"}}}},"responses":{"200":{"description":"Positions found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsResponse"}}}},"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionsResponse"}}}},"400":{"description":"Invalid network"},"500":{"description":"An unknown error occurred"}},"summary":"Get positions for an address","tags":["Positions"]}}},"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://hoodi.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://hoodi.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","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","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},"unique_validators_count":{"type":"number","example":10},"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":{"all":{"type":"number","description":"Cluster effectiveness for alltime."}},"required":["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","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"]},"RegistrationMessageDto":{"type":"object","properties":{"fee_recipient":{"type":"string"},"gas_limit":{"type":"string"},"timestamp":{"type":"string"},"pubkey":{"type":"string"}},"required":["fee_recipient","gas_limit","timestamp","pubkey"]},"PartialRegistrationDto":{"type":"object","properties":{"message":{"$ref":"#/components/schemas/RegistrationMessageDto"},"signature":{"type":"string"}},"required":["message","signature"]},"FeeRecipientDto":{"type":"object","properties":{"partial_registrations":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/PartialRegistrationDto"}}},"required":["partial_registrations"]},"FetchQueryDto":{"type":"object","properties":{"pubkeys":{"description":"Optional list of validator pubkeys to filter by. If omitted or empty, returns all validators with registrations.","example":["0xdeadbeef...","0xcafebabe..."],"type":"array","items":{"type":"string"}}}},"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, rounded to 2 decimal places)","example":67.45},"total_claimed_balance_eth_denominated":{"type":"number","description":"Total claimed balance in ETH (from daily fees/revenue data for the snapshot date, rounded to 2 decimal places)","example":71.23},"total_eth_transferred":{"type":"number","description":"Total ETH transferred (from daily fees/revenue data for the snapshot date, rounded to 2 decimal places)","example":4.56},"total_revenue":{"type":"number","description":"Total revenue (from daily fees/revenue data for the snapshot date, rounded to 2 decimal places)","example":142.89},"total_fees_eth_denominated":{"type":"number","description":"Total fees in ETH (from daily fees/revenue data for the snapshot date, rounded to 2 decimal places)","example":504.12}},"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"]},"PositionsRequestDto":{"type":"object","properties":{"additionalAddresses":{"description":"Additional addresses to search (e.g. split addresses from getRelatedSplits, DeFi wrapper WA)","type":"array","items":{"type":"string"}}}},"ResolvedRecipients":{"type":"object","properties":{"principal_recipient":{"type":"string","description":"OVM/OWR: principal recipient address"},"reward_recipient":{"type":"string","description":"OVM/OWR: reward recipient address"},"threshold":{"type":"string","description":"OWR only: threshold in wei"},"split_recipients":{"description":"Split: list of split recipients","type":"array","items":{"type":"string"}}}},"PositionValidator":{"type":"object","properties":{"pubkey":{"type":"string","description":"Validator public key"},"withdrawal_address":{"type":"string","description":"Withdrawal address"},"fee_recipient_address":{"type":"string","description":"Fee recipient address"},"withdrawal_type":{"type":"string","description":"Type of address: \"eoa\" (default), \"splitter\", or V2: \"ovm\"/\"owr\".","enum":["eoa","splitter","ovm","owr"]},"fee_recipient_type":{"type":"string","description":"Type of address: \"eoa\" (default), \"splitter\", or V2: \"ovm\"/\"owr\".","enum":["eoa","splitter","ovm","owr"]},"withdrawal_resolved":{"description":"V2: resolved recipients for non-EOA withdrawal addresses","allOf":[{"$ref":"#/components/schemas/ResolvedRecipients"}]},"fee_recipient_resolved":{"description":"V2: resolved recipients for non-EOA fee recipients","allOf":[{"$ref":"#/components/schemas/ResolvedRecipients"}]}},"required":["pubkey","withdrawal_address","fee_recipient_address"]},"PositionCluster":{"type":"object","properties":{"lock_hash":{"type":"string","description":"Cluster lock hash"},"cluster_name":{"type":"string","description":"Cluster name"},"num_validators_total":{"type":"number","description":"Total validators in this cluster"},"validators":{"description":"Validators matched by search addresses","type":"array","items":{"$ref":"#/components/schemas/PositionValidator"}},"total_balance_eth":{"type":"number","description":"Sum of balance_eth for matched validators (latest snapshot)"},"avg_effectiveness":{"type":"number","description":"Average effectiveness for matched validators (latest snapshot)"}},"required":["lock_hash","cluster_name","num_validators_total","validators","total_balance_eth","avg_effectiveness"]},"PositionsResponse":{"type":"object","properties":{"positions":{"type":"array","items":{"$ref":"#/components/schemas/PositionCluster"}}},"required":["positions"]}}}}