Introduction
Welcome to the Pool Detective API! The Pool Detective is a project of the Digital Currency Initiative at the MIT Media Lab.
The Pool Detective tracks the behavior of the largest mining pools in the most popular Proof-of-Work cryptocurrencies. We compare the work sent to us by these pools against the block data observed by both official full nodes from the corresponding cryptocurrency, as well as blocks we observe being propagated using a custom observer on the peer-to-peer networks.
Publicly available endpoints
There are API endpoints that are public (start with /public
) which you can freely request. Other endpoints require a valid API key.
Rate limits
Unauthenticated requests are limited to 12 requests per minute per IP address. Authenticated requests are limited to 120 requests per minute per IP address.
Authentication
To authenticate with an API key, use this code:
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here"
-H "X-Api-Key: myapikey"
Make sure to replace
myapikey
with your API key.
Pool Detective uses API keys to regulate access to the API. Pool Detective expects for the API key to be included in all API requests to the server in a header that looks like the following:
X-Api-Key: myapikey
Get an API Key
You can obtain an API key by sending an e-mail to pooldetective@mit.edu
.
Feedback, questions, ideas
Feel free to leave your feedback by creating a new issue in the PoolDetective Github repository. This repository also contains the code underpinning the API and PoolDetective, and contains instructions on how to run it yourself.
Public API
The Public API does not require an API key. You can retrieve this data without authenticating, but you are limited to 12 requests per minute.
If you have an API key, you can call these same APIs by removing the /public
portion of the URL and supplying your API-Key with the request. You will then not be limited to 12 requests per minute, but 120.
Get All Coins
This endpoint retrieves all the coins the Pool Detective is tracking.
HTTP Request
GET https://pooldetective.org/api/public/coins
curl "https://pooldetective.org/api/public/coins"
The above command returns JSON structured like this:
[
{
"id":1,
"name":"Bitcoin"
},
{
"id":2,
"name":"Bitcoin SV"
},
{
"id":3,
"name":"Bitcoin Cash"
}
]
Get the pools that we are mining a specific coin on
curl "https://pooldetective.org/api/public/coins/2/pools"
The above command returns JSON structured like this:
[
{
"id": 1,
"name": "Slushpool"
},
{
"id": 2,
"name": "Antpool"
},
{
"id": 3,
"name": "F2Pool"
}
]
This endpoint retrieves which pools we are using to mine a specific coin
HTTP Request
GET https://pooldetective.org/api/public/coins/<ID>/pools
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the coin to retrieve the pools for |
Get All Pools
curl "https://pooldetective.org/api/public/pools"
The above command returns JSON structured like this:
[
{
"id": 1,
"name": "Slushpool"
},
{
"id": 2,
"name": "Antpool"
},
{
"id": 3,
"name": "F2Pool"
}
]
This endpoint retrieves all the pools the Pool Detective is tracking.
HTTP Request
GET https://pooldetective.org/api/public/pools
Get the coins we are mining on a pool
curl "https://pooldetective.org/api/public/pools/1/coins"
The above command returns JSON structured like this:
[
{
"id": 1,
"name": "Bitcoin"
},
{
"id": 3,
"name": "Bitcoin Cash"
},
{
"id": 5,
"name": "Litecoin"
}
]
This endpoint retrieves which coins we are mining on the given pool.
HTTP Request
GET https://pooldetective.org/api/public/pools/<ID>/coins
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the pool to retrieve the coins for |
Get Wrong Work that we discovered yesterday
curl "https://pooldetective.org/api/public/wrongwork/yesterday"
The above command returns JSON structured like this:
[
{
"observedOn": "2020-09-10T00:00:00Z",
"poolId": 2,
"expectedCoinId": 3,
"expectedCoinName": "Bitcoin Cash",
"stratumHost": "stratum.antpool.com",
"location": "Netherlands",
"wrongCoinId": 1,
"wrongCoinName": "Bitcoin",
"totalJobs": 2581,
"wrongJobs": 169,
"totalTimeMs": 86408050,
"wrongTimeMs": 77097
},
{
"observedOn": "2020-09-10T00:00:00Z",
"poolId": 7,
"expectedCoinId": 1,
"expectedCoinName": "Bitcoin",
"stratumHost": "stratum.btc.top",
"location": "Netherlands",
"wrongCoinId": 2,
"wrongCoinName": "Bitcoin SV",
"totalJobs": 3163,
"wrongJobs": 13,
"totalTimeMs": 86407440,
"wrongTimeMs": 3
}
]
This endpoint retrieves the wrong work being given by pools. When we connect to a pool, we expect the work to be for coin expectedCoinId
. But if we receive other work (that we can resolve to another blockchain), we are classifying this as wrong. This endpoint will show the coin we actually got work for in wrongCoinId
. It will also show the share of wrong work in both number of jobs (we got wrongJobs
jobs of the wrong coin, and totalJobs
in total from the pool during the entire day yesterday) as well as in time. We calculate the time for a single job to be the time we received it until we received the next one from the same pool connection. totalTimeMs
is the total time spent on jobs during the day (usually this is 86400 seconds in 24 hours). wrongTimeMs
is the time we would be able to spend working on the wrong jobs if we switched to them instantly, measured in milliseconds.
HTTP Request
GET https://pooldetective.org/api/public/wrongwork/yesterday
Get Unresolved work that we discovered yesterday
curl "https://pooldetective.org/api/public/unresolvedwork/yesterday"
The above command returns JSON structured like this:
[
{
"observedOn": "2020-09-10T00:00:00Z",
"poolId": 2,
"expectedCoinId": 8,
"expectedCoinName": "Dash",
"stratumHost": "stratum-dash.antpool.com",
"location": "Netherlands",
"wrongCoinId": -1,
"wrongCoinName": "No Coin",
"totalJobs": 2284,
"wrongJobs": 2,
"totalTimeMs": 86383770,
"wrongTimeMs": 100008
},
{
"observedOn": "2020-09-10T00:00:00Z",
"poolId": 3,
"expectedCoinId": 8,
"expectedCoinName": "Dash",
"stratumHost": "dash.f2pool.com",
"location": "Netherlands",
"wrongCoinId": -1,
"wrongCoinName": "No Coin",
"totalJobs": 11911,
"wrongJobs": 1,
"totalTimeMs": 86392261,
"wrongTimeMs": 2328
}
]
This endpoint retrieves the unresolved work being given by pools. When we connect to a pool, we expect the work to be for coin expectedCoinId
. But if we receive work we cannot match to any of our known blocks, we call this unresolved. Unresolved work is expected to generally be work on blocks that were orphaned and that our full nodes never received, so we don't know about their existence. It could also mean that this is work done on blocks from another chain we do not happen to monitor. It will also show the share of unresolved work in both number of jobs (we got wrongJobs
jobs we couldn't resolve, and totalJobs
in total from the pool during the entire day yesterday) as well as in time. We calculate the time for a single job to be the time we received it until we received the next one from the same pool connection. totalTimeMs
is the total time spent on jobs during the day (usually this is 86400 seconds in 24 hours). wrongTimeMs
is the time we would be able to spend working on the unresolved jobs if we switched to them instantly, measured in milliseconds.
HTTP Request
GET https://pooldetective.org/api/public/unresolvedwork/yesterday
Coins
Public endpoints:
- Get all coins -
/api/public/coins
- Get pools for a coin -
/api/public/coins/<ID>/pools
Get a specific coin
curl "https://pooldetective.org/api/coins/2" \
-H "X-Api-Key: myapikey"
The above command returns JSON structured like this:
{
"id": 2,
"minHeight": 0,
"maxHeight": 627866,
"numBlocks": 627874,
"tipHash": "0000000000000000012977bd1bf57513e8891c482bc9ba09d6b511219583842d",
"algorithmName": "SHA-256",
"algorithmID": 1
}
This endpoint retrieves details for a specific coin
HTTP Request
GET https://pooldetective.org/api/coins/<ID>
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the coin to retrieve |
Get the details about a coins we are mining on a pool
curl "https://pooldetective.org/api/coins/1/pools/2" \
-H "X-Api-Key: myapikey"
The above command returns JSON structured like this:
{
"observers": [
{
"id": 17,
"location": "Singapore",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-24T11:19:39.705958Z",
"lastShareFound": "2020-03-24T11:30:58.915025Z",
"currentDifficulty": 512
},
{
"id": 10,
"location": "Netherlands",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-26T14:20:10.953866Z",
"lastShareFound": "2020-03-26T14:20:06.191896Z",
"currentDifficulty": 512
},
{
"id": 24,
"location": "United States West",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-26T14:20:05.633823Z",
"lastShareFound": "2020-03-26T14:20:17.824093Z",
"currentDifficulty": 512
},
{
"id": 3,
"location": "Australia",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-26T14:20:06.063283Z",
"lastShareFound": "2020-03-26T14:20:19.883102Z",
"currentDifficulty": 512
},
{
"id": 31,
"location": "United States East",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-25T06:25:28.84478Z",
"lastShareFound": "2020-03-25T06:40:26.719632Z",
"currentDifficulty": 512
}
]
}
This endpoint retrieves details about how we are currently mining the given coin at the given pool. It returns details about the last time we got a job from the pool, and the last time we found a valid proof-of-work share. It also returns the current mining difficulty on this pool.
HTTP Request
GET https://pooldetective.org/api/coins/<CoinID>/pools/<PoolID>
URL Parameters
Parameter | Description |
---|---|
CoinID | The ID of the coin to retrieve details for |
PoolID | The ID of the pool we want to retrieve mining details for about mining coin CoinID |
Pools
Public endpoints:
- Get all pools -
/api/public/pools
- Get coins for a pool -
/api/public/pools/<ID>/coins
Get a specific pool
curl "https://pooldetective.org/api/pools/1" \
-H "X-Api-Key: myapikey"
The above command returns JSON structured like this:
{
"id": 1,
"name": "Slushpool"
}
This endpoint retrieves details for a specific pool
HTTP Request
GET https://pooldetective.org/api/pools/<ID>
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the pool to retrieve |
Get the details about a coins we are mining on a pool
curl "https://pooldetective.org/api/pools/2/coins/1" \
-H "X-Api-Key: myapikey"
The above command returns JSON structured like this:
{
"observers": [
{
"id": 17,
"location": "Singapore",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-24T11:19:39.705958Z",
"lastShareFound": "2020-03-24T11:30:58.915025Z",
"currentDifficulty": 512
},
{
"id": 10,
"location": "Netherlands",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-26T14:20:10.953866Z",
"lastShareFound": "2020-03-26T14:20:06.191896Z",
"currentDifficulty": 512
},
{
"id": 24,
"location": "United States West",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-26T14:20:05.633823Z",
"lastShareFound": "2020-03-26T14:20:17.824093Z",
"currentDifficulty": 512
},
{
"id": 3,
"location": "Australia",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-26T14:20:06.063283Z",
"lastShareFound": "2020-03-26T14:20:19.883102Z",
"currentDifficulty": 512
},
{
"id": 31,
"location": "United States East",
"poolServer": "stratum.antpool.com",
"lastJobReceived": "2020-03-25T06:25:28.84478Z",
"lastShareFound": "2020-03-25T06:40:26.719632Z",
"currentDifficulty": 512
}
]
}
This endpoint retrieves details about how we are currently mining the given coin at the given pool. It returns details about the last time we got a job from the pool, and the last time we found a valid proof-of-work share. It also returns the current mining difficulty on this pool.
HTTP Request
GET https://pooldetective.org/api/pools/<PoolID>/coins/<CoinID>
URL Parameters
Parameter | Description |
---|---|
PoolID | The ID of the pool to retrieve details for |
CoinID | The ID of the coin we want to retrieve mining details for in pool PoolID |
Analysis
Public endpoints:
- Get wrong work from yesterday -
/api/public/wrongwork/yesterday
- Get unresolved work from yesterday -
/api/public/unresolvedwork/yesterday
Get Wrong Work that we discovered on a specific date
curl "https://pooldetective.org/api/wrongwork/2020-09-01" \
-H "X-Api-Key: myapikey"
The above command returns JSON structured like this:
[
{
"observedOn": "2020-09-10T00:00:00Z",
"poolId": 2,
"expectedCoinId": 3,
"expectedCoinName": "Bitcoin Cash",
"stratumHost": "stratum.antpool.com",
"location": "Netherlands",
"wrongCoinId": 1,
"wrongCoinName": "Bitcoin",
"totalJobs": 2581,
"wrongJobs": 169,
"totalTimeMs": 86408050,
"wrongTimeMs": 77097
},
{
"observedOn": "2020-09-10T00:00:00Z",
"poolId": 7,
"expectedCoinId": 1,
"expectedCoinName": "Bitcoin",
"stratumHost": "stratum.btc.top",
"location": "Netherlands",
"wrongCoinId": 2,
"wrongCoinName": "Bitcoin SV",
"totalJobs": 3163,
"wrongJobs": 13,
"totalTimeMs": 86407440,
"wrongTimeMs": 3
}
]
This endpoint retrieves the wrong work being given by pools. When we connect to a pool, we expect the work to be for coin expectedCoinId
. But if we receive other work (that we can resolve to another blockchain), we are classifying this as wrong. This endpoint will show the coin we actually got work for in wrongCoinId
. It will also show the share of wrong work in both number of jobs (we got wrongJobs
jobs of the wrong coin, and totalJobs
in total from the pool during the entire day yesterday) as well as in time. We calculate the time for a single job to be the time we received it until we received the next one from the same pool connection. totalTimeMs
is the total time spent on jobs during the day (usually this is 86400 seconds in 24 hours). wrongTimeMs
is the time we would be able to spend working on the wrong jobs if we switched to them instantly, measured in milliseconds.
HTTP Request
GET https://pooldetective.org/api/wrongwork/<DATE>
URL Parameters
Parameter | Description |
---|---|
DATE | The date you want the data from in YYYY-MM-DD format |
Get Unresolved work that we discovered on a specific date
curl "https://pooldetective.org/api/unresolvedwork/2020-09-01" \
-H "X-Api-Key: myapikey"
The above command returns JSON structured like this:
[
{
"observedOn": "2020-09-10T00:00:00Z",
"poolId": 2,
"expectedCoinId": 8,
"expectedCoinName": "Dash",
"stratumHost": "stratum-dash.antpool.com",
"location": "Netherlands",
"wrongCoinId": -1,
"wrongCoinName": "No Coin",
"totalJobs": 2284,
"wrongJobs": 2,
"totalTimeMs": 86383770,
"wrongTimeMs": 100008
},
{
"observedOn": "2020-09-10T00:00:00Z",
"poolId": 3,
"expectedCoinId": 8,
"expectedCoinName": "Dash",
"stratumHost": "dash.f2pool.com",
"location": "Netherlands",
"wrongCoinId": -1,
"wrongCoinName": "No Coin",
"totalJobs": 11911,
"wrongJobs": 1,
"totalTimeMs": 86392261,
"wrongTimeMs": 2328
}
]
This endpoint retrieves the unresolved work being given by pools. When we connect to a pool, we expect the work to be for coin expectedCoinId
. But if we receive work we cannot match to any of our known blocks, we call this unresolved. Unresolved work is expected to generally be work on blocks that were orphaned and that our full nodes never received, so we don't know about their existence. It could also mean that this is work done on blocks from another chain we do not happen to monitor. It will also show the share of unresolved work in both number of jobs (we got wrongJobs
jobs we couldn't resolve, and totalJobs
in total from the pool during the entire day yesterday) as well as in time. We calculate the time for a single job to be the time we received it until we received the next one from the same pool connection. totalTimeMs
is the total time spent on jobs during the day (usually this is 86400 seconds in 24 hours). wrongTimeMs
is the time we would be able to spend working on the unresolved jobs if we switched to them instantly, measured in milliseconds.
HTTP Request
GET https://pooldetective.org/api/unresolvedwork/<DATE>
URL Parameters
Parameter | Description |
---|---|
DATE | The date you want the data from in YYYY-MM-DD format |
Errors
The Pool Detective API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- Your API key is wrong. |
403 | Forbidden -- The resource you're trying to open is not accessible to your API key |
404 | Not Found -- The resource you're trying to open is not found |
405 | Method Not Allowed -- You tried to access a resource using the wrong HTTP verb |
406 | Not Acceptable -- You requested a format that isn't json. |
429 | Too Many Requests -- You've hit the rate limit |
500 | Internal Server Error -- We had a problem with our server. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |