NAV
cURL

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 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 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 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.