Connecting to Planetmint

Planetmint enables you to connect to it via variaous ways:

  • Bindings or drivers for varioues languages exist

  • RESTful APIs and direct database queries

Details are listed below.

Drivers & Bindings

Connectors to Planetmint are referred to as drivers within the community. A driver is used to create valid transactions, to generate key pairs, to sign transactions and to post the transaction to the Planetmint API.

These drivers or bindings were originally created by the original BigchainDB team:

These drivers and tools were created by the BigchainDB community:

Warning

Some of these projects are a work in progress, but may still be useful. Others might not work with the latest version of Planetmint.

HTTP Client-Server API

This page assumes you already know an API Root URL for a Planetmint node or reverse proxy. It should be something like https://example.com:9984 or https://12.34.56.78:9984.

If you set up a Planetmint node or reverse proxy yourself, and you’re not sure what the API Root URL is, then see the last section of this page for help.

Planetmint Root URL

If you send an HTTP GET request to the Planetmint Root URL e.g. http://localhost:9984 or https://example.com:9984 (with no /api/v1/ on the end), then you should get an HTTP response with something like the following in the body:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "api": {
    "v1": {
      "assets": "/api/v1/assets/",
      "blocks": "/api/v1/blocks/",
      "docs": "https://docs.planetmint.io/projects/server/en/v1.0.1/http-client-server-api.html",
      "metadata": "/api/v1/metadata/",
      "outputs": "/api/v1/outputs/",
      "streamedblocks": "ws://localhost:9985/api/v1/streams/valid_blocks",
      "streams": "ws://localhost:9985/api/v1/streams/valid_transactions",
      "transactions": "/api/v1/transactions/",
      "validators": "/api/v1/validators"
    }
  },
  "docs": "https://docs.planetmint.io/projects/server/en/v1.0.1/",
  "software": "Planetmint",
  "version": "1.0.1"
}

API Root Endpoint

If you send an HTTP GET request to the API Root Endpoint e.g. http://localhost:9984/api/v1/ or https://example.com:9984/api/v1/, then you should get an HTTP response that allows you to discover the Planetmint API endpoints:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "assets": "/assets/",
  "blocks": "/blocks/",
  "docs": "https://docs.planetmint.io/projects/server/en/v1.0.1/http-client-server-api.html",
  "metadata": "/metadata/",
  "outputs": "/outputs/",
  "streamedblocks": "ws://localhost:9985/api/v1/streams/valid_blocks",
  "streams": "ws://localhost:9985/api/v1/streams/valid_transactions",
  "transactions": "/transactions/",
  "validators": "/validators"
}

Transactions Endpoint

Note

If you want to do more sophisticated queries than those provided by the Planetmint HTTP API, then one option is to connect to MongoDB directly (if possible) and do whatever queries MongoDB allows. For more about that option, see the page about querying Planetmint.

GET /api/v1/transactions/{transaction_id}

Get the transaction with the ID transaction_id.

If a transaction with ID transaction_id has been included in a committed block, then this endpoint returns that transaction, otherwise the response will be 404 Not Found.

Parameters
  • transaction_id (hex string) – transaction ID

Example request:

GET /api/v1/transactions/6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2 HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "asset": {
    "data": {
      "msg": "Hello Planetmint!"
    }
  },
  "id": "6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2",
  "inputs": [
    {
      "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUBcdRj6EnG3MPl47m3XPd1HNfe7q3WL4T6MewNNnat33UvzVnPHo_vossv57M7L064VwrYMLGp097H7IeHpDngK",
      "fulfills": null,
      "owners_before": [
        "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
      ]
    }
  ],
  "metadata": {
    "sequence": 0
  },
  "operation": "CREATE",
  "outputs": [
    {
      "amount": "1",
      "condition": {
        "details": {
          "public_key": "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD",
          "type": "ed25519-sha-256"
        },
        "uri": "ni:///sha-256;PNYwdxaRaNw60N6LDFzOWO97b8tJeragczakL8PrAPc?fpt=ed25519-sha-256&cost=131072"
      },
      "public_keys": [
        "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
      ]
    }
  ],
  "version": "2.0"
}
Response Headers
Status Codes
  • 200 OK – A transaction with that ID was found.

  • 404 Not Found – A transaction with that ID was not found.

GET /api/v1/transactions

Requests to the /api/v1/transactions endpoint without any query parameters will get a response status code 400 Bad Request.

GET /api/v1/transactions?asset_id={asset_id}&operation={CREATE|TRANSFER}&last_tx={true|false}

Get a list of transactions that use an asset with the ID asset_id.

If operation is CREATE, then the CREATE transaction which created the asset with ID asset_id will be returned.

If operation is TRANSFER, then every TRANSFER transaction involving the asset with ID asset_id will be returned. This allows users to query the entire history or provenance of an asset.

If operation is not included, then every transaction involving the asset with ID asset_id will be returned.

if last_tx is set to true, only the last transaction is returned instead of all transactions with the given asset_id.

This endpoint returns transactions only if they are in committed blocks.

Query Parameters
  • operation (string) – (Optional) CREATE or TRANSFER.

  • asset_id (string) – asset ID.

  • last_tx (string) – (Optional) true or false.

Example request:

GET /api/v1/transactions?operation=TRANSFER&asset_id=6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2 HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[{
  "asset": {
    "id": "6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2"
  },
  "id": "2bf8ae1e3bc889a26df129dd6bbe6ccab30d1ae8e9e434fae1c4446042a68931",
  "inputs": [
    {
      "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUA90mMa9AWnbI70CUSVgzV9kRFf3tQ20RUIczNFqmwg9xrpOk_5uNoJB4bWRIojZmUhEyxSueCHLpqPXCEuyisE",
      "fulfills": {
        "output_index": 0,
        "transaction_id": "6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2"
      },
      "owners_before": [
        "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
      ]
    }
  ],
  "metadata": {
    "sequence": 1
  },
  "operation": "TRANSFER",
  "outputs": [
    {
      "amount": "1",
      "condition": {
        "details": {
          "public_key": "3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9",
          "type": "ed25519-sha-256"
        },
        "uri": "ni:///sha-256;lu6ov4AKkee6KWGnyjOVLBeyuP0bz4-O6_dPi15eYUc?fpt=ed25519-sha-256&cost=131072"
      },
      "public_keys": [
        "3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9"
      ]
    }
  ],
  "version": "2.0"
},
{
  "asset": {
    "id": "6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2"
  },
  "id": "b9b614175eaed7cc93d9b80ebc2a91d35ae31928a7c218ae982272bb1785ef16",
  "inputs": [
    {
      "fulfillment": "pGSAICw7Ul-c2lG6NFbHp3FbKRC7fivQcNGO7GS4wV3A-1QggUDi2bAVKJgEyE3LzMrAnAu1PnNs9DbDNkABaY6j3OCNEVwNVNg3V3qELOFNnH8vGUevREr4E-8Vb1Kzk4VR71MO",
      "fulfills": {
        "output_index": 0,
        "transaction_id": "2bf8ae1e3bc889a26df129dd6bbe6ccab30d1ae8e9e434fae1c4446042a68931"
      },
      "owners_before": [
        "3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9"
      ]
    }
  ],
  "metadata": {
    "sequence": 2
  },
  "operation": "TRANSFER",
  "outputs": [
    {
      "amount": "1",
      "condition": {
        "details": {
          "public_key": "3Af3fhhjU6d9WecEM9Uw5hfom9kNEwE7YuDWdqAUssqm",
          "type": "ed25519-sha-256"
        },
        "uri": "ni:///sha-256;Ll1r0LzgHUvWB87yIrNFYo731MMUEypqvrbPATTbuD4?fpt=ed25519-sha-256&cost=131072"
      },
      "public_keys": [
        "3Af3fhhjU6d9WecEM9Uw5hfom9kNEwE7YuDWdqAUssqm"
      ]
    }
  ],
  "version": "2.0"
}]
Response Headers
Status Codes
  • 200 OK – A list of transactions containing an asset with ID asset_id was found and returned.

  • 400 Bad Request – The request wasn’t understood by the server, e.g. the asset_id querystring was not included in the request.

POST /api/v1/transactions?mode={mode}

This endpoint is used to send a transaction to a Planetmint network. The transaction is put in the body of the request.

Query Parameters
  • mode (string) – (Optional) One of the three supported modes to send a transaction: async, sync, commit. The default is async.

Once the posted transaction arrives at a Planetmint node, that node will check to see if the transaction is valid. If it’s invalid, the node will return an HTTP 400 (error). Otherwise, the node will send the transaction to Tendermint (in the same node) using the Tendermint broadcast API.

The meaning of the mode query parameter is inherited from the mode parameter in Tendermint’s broadcast API. mode=async means the HTTP response will come back immediately, before Tendermint asks Planetmint Server to check the validity of the transaction (a second time). mode=sync means the HTTP response will come back after Tendermint gets a response from Planetmint Server regarding the validity of the transaction. mode=commit means the HTTP response will come back once the transaction is in a committed block.

Note

In the async and sync modes, after a successful HTTP response is returned, the transaction may still be rejected later on. All the transactions are recorded internally by Tendermint in WAL (Write-Ahead Log) before the HTTP response is returned. Nevertheless, the following should be noted:

  • Transactions in WAL including the failed ones are not exposed in any of the Planetmint or Tendermint APIs.

  • Transactions are never fetched from WAL. WAL is never replayed.

  • A critical failure (e.g. the system is out of disk space) may occur preventing transactions from being stored in WAL, even when the HTTP response indicates a success.

  • If a transaction fails the validation because it conflicts with the other transactions of the same block, Tendermint includes it into its block, but Planetmint does not store these transactions and does not offer any information about them in the APIs.

Note

The posted transaction should be valid. The relevant Planetmint Transactions Spec explains how to build a valid transaction and how to check if a transaction is valid. One would normally use a driver such as the Planetmint Python Driver to build a valid transaction.

Note

A client can subscribe to the WebSocket Event Stream API to listen for committed transactions.

Example request:

POST /api/v1/transactions?mode=async HTTP/1.1
Host: example.com
Content-Type: application/json

{
  "asset": {
    "data": {
      "msg": "Hello Planetmint!"
    }
  },
  "id": "6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2",
  "inputs": [
    {
      "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUBcdRj6EnG3MPl47m3XPd1HNfe7q3WL4T6MewNNnat33UvzVnPHo_vossv57M7L064VwrYMLGp097H7IeHpDngK",
      "fulfills": null,
      "owners_before": [
        "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
      ]
    }
  ],
  "metadata": {
    "sequence": 0
  },
  "operation": "CREATE",
  "outputs": [
    {
      "amount": "1",
      "condition": {
        "details": {
          "public_key": "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD",
          "type": "ed25519-sha-256"
        },
        "uri": "ni:///sha-256;PNYwdxaRaNw60N6LDFzOWO97b8tJeragczakL8PrAPc?fpt=ed25519-sha-256&cost=131072"
      },
      "public_keys": [
        "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
      ]
    }
  ],
  "version": "2.0"
}

Example response:

HTTP/1.1 202 Accepted
Content-Type: application/json

{
  "asset": {
    "data": {
      "msg": "Hello Planetmint!"
    }
  },
  "id": "6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2",
  "inputs": [
    {
      "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUBcdRj6EnG3MPl47m3XPd1HNfe7q3WL4T6MewNNnat33UvzVnPHo_vossv57M7L064VwrYMLGp097H7IeHpDngK",
      "fulfills": null,
      "owners_before": [
        "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
      ]
    }
  ],
  "metadata": {
    "sequence": 0
  },
  "operation": "CREATE",
  "outputs": [
    {
      "amount": "1",
      "condition": {
        "details": {
          "public_key": "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD",
          "type": "ed25519-sha-256"
        },
        "uri": "ni:///sha-256;PNYwdxaRaNw60N6LDFzOWO97b8tJeragczakL8PrAPc?fpt=ed25519-sha-256&cost=131072"
      },
      "public_keys": [
        "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
      ]
    }
  ],
  "version": "2.0"
}
Response Headers
Status Codes
  • 202 Accepted – The meaning of this response depends on the value of the mode parameter. See above.

  • 400 Bad Request – The posted transaction was invalid.

POST /api/v1/transactions

This endpoint (without any parameters) will push a new transaction. Since no mode parameter is included, the default mode is assumed: async.

Transaction Outputs

The /api/v1/outputs endpoint returns transactions outputs filtered by a given public key, and optionally filtered to only include either spent or unspent outputs.

Note

If you want to do more sophisticated queries than those provided by the Planetmint HTTP API, then one option is to connect to MongoDB directly (if possible) and do whatever queries MongoDB allows. For more about that option, see the page about querying Planetmint.

GET /api/v1/outputs

Get transaction outputs by public key. The public_key parameter must be a base58 encoded ed25519 public key associated with transaction output ownership.

Returns a list of transaction outputs.

Parameters
  • public_key – Base58 encoded public key associated with output ownership. This parameter is mandatory and without it the endpoint will return a 400 response code.

  • spent – (Optional) Boolean value (true or false) indicating if the result set should include only spent or only unspent outputs. If not specified, the result includes all the outputs (both spent and unspent) associated with the public_key.

GET /api/v1/outputs?public_key={public_key}

Return all outputs, both spent and unspent, for the public_key.

Example request:

GET /api/v1/outputs?public_key=1AAAbbb...ccc HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "output_index": 0,
    "transaction_id": "2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e"
  },
  {
    "output_index": 1,
    "transaction_id": "2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e"
  }
]
Status Codes
  • 200 OK – A list of outputs was found and returned in the body of the response.

  • 400 Bad Request – The request wasn’t understood by the server, e.g. the public_key querystring was not included in the request.

GET /api/v1/outputs?public_key={public_key}&spent=true

Return all spent outputs for public_key.

Example request:

GET /api/v1/outputs?public_key=1AAAbbb...ccc&spent=true HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "output_index": 0,
    "transaction_id": "2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e"
  }
]
Status Codes
  • 200 OK – A list of outputs were found and returned in the body of the response.

  • 400 Bad Request – The request wasn’t understood by the server, e.g. the public_key querystring was not included in the request.

GET /api/v1/outputs?public_key={public_key}&spent=false

Return all unspent outputs for public_key.

Example request:

GET /api/v1/outputs?public_key=1AAAbbb...ccc&spent=false HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "output_index": 1,
    "transaction_id": "2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e"
  }
]
Status Codes
  • 200 OK – A list of outputs were found and returned in the body of the response.

  • 400 Bad Request – The request wasn’t understood by the server, e.g. the public_key querystring was not included in the request.

Assets

Note

If you want to do more sophisticated queries than those provided by the Planetmint HTTP API, then one option is to connect to MongoDB directly (if possible) and do whatever queries MongoDB allows. For more about that option, see the page about querying Planetmint.

GET /api/v1/assets

Return all the assets that match a given text search.

Query Parameters
  • search (string) – Text search string to query.

  • limit (int) – (Optional) Limit the number of returned assets. Defaults to 0 meaning return all matching assets.

GET /api/v1/assets/?search={search}

Return all assets that match a given text search.

Note

The id of the asset is the same id of the CREATE transaction that created the asset.

Note

You can use assets/?search or assets?search.

If no assets match the text search it returns an empty list.

If the text string is empty or the server does not support text search, a 400 Bad Request is returned.

The results are sorted by text score. For more information about the behavior of text search, see MongoDB text search behavior.

Example request:

GET /api/v1/assets/?search=planetmint HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-type: application/json

[
    {
        "data": {"msg": "Hello Planetmint 1!"},
        "id": "51ce82a14ca274d43e4992bbce41f6fdeb755f846e48e710a3bbb3b0cf8e4204"
    },
    {
        "data": {"msg": "Hello Planetmint 2!"},
        "id": "b4e9005fa494d20e503d916fa87b74fe61c079afccd6e084260674159795ee31"
    },
    {
        "data": {"msg": "Hello Planetmint 3!"},
        "id": "fa6bcb6a8fdea3dc2a860fcdc0e0c63c9cf5b25da8b02a4db4fb6a2d36d27791"
    }
]
Response Headers
Status Codes
  • 200 OK – The query was executed successfully.

  • 400 Bad Request – The query was not executed successfully. Returned if the text string is empty or the server does not support text search.

GET /api/v1/assets?search={search}&limit={n_documents}

Return at most n_documents assets that match a given text search.

If no assets match the text search it returns an empty list.

If the text string is empty or the server does not support text search, a 400 Bad Request is returned.

The results are sorted by text score. For more information about the behavior of text search, see MongoDB text search behavior.

Example request:

GET /api/v1/assets?search=planetmint&limit=2 HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-type: application/json

[
    {
        "data": {"msg": "Hello Planetmint 1!"},
        "id": "51ce82a14ca274d43e4992bbce41f6fdeb755f846e48e710a3bbb3b0cf8e4204"
    },
    {
        "data": {"msg": "Hello Planetmint 2!"},
        "id": "b4e9005fa494d20e503d916fa87b74fe61c079afccd6e084260674159795ee31"
    },
]
Response Headers
Status Codes
  • 200 OK – The query was executed successfully.

  • 400 Bad Request – The query was not executed successfully. Returned if the text string is empty or the server does not support text search.

Transaction Metadata

Note

If you want to do more sophisticated queries than those provided by the Planetmint HTTP API, then one option is to connect to MongoDB directly (if possible) and do whatever queries MongoDB allows. For more about that option, see the page about querying Planetmint.

GET /api/v1/metadata

Return all the metadata objects that match a given text search.

Query Parameters
  • search (string) – Text search string to query.

  • limit (int) – (Optional) Limit the number of returned metadata objects. Defaults to 0 meaning return all matching objects.

GET /api/v1/metadata/?search={search}

Return all metadata objects that match a given text search.

Note

The id of the metadata is the same id of the transaction where it was defined.

Note

You can use metadata/?search or metadata?search.

If no metadata objects match the text search it returns an empty list.

If the text string is empty or the server does not support text search, a 400 Bad Request is returned.

The results are sorted by text score. For more information about the behavior of text search, see MongoDB text search behavior.

Example request:

GET /api/v1/metadata/?search=planetmint HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-type: application/json

[
    {
        "metadata": {"metakey1": "Hello Planetmint 1!"},
        "id": "51ce82a14ca274d43e4992bbce41f6fdeb755f846e48e710a3bbb3b0cf8e4204"
    },
    {
        "metadata": {"metakey2": "Hello Planetmint 2!"},
        "id": "b4e9005fa494d20e503d916fa87b74fe61c079afccd6e084260674159795ee31"
    },
    {
        "metadata": {"metakey3": "Hello Planetmint 3!"},
        "id": "fa6bcb6a8fdea3dc2a860fcdc0e0c63c9cf5b25da8b02a4db4fb6a2d36d27791"
    }
]
Response Headers
Status Codes
  • 200 OK – The query was executed successfully.

  • 400 Bad Request – The query was not executed successfully. Returned if the text string is empty or the server does not support text search.

GET /api/v1/metadata/?search={search}&limit={n_documents}

Return at most n_documents metadata objects that match a given text search.

If no metadata objects match the text search it returns an empty list.

If the text string is empty or the server does not support text search, a 400 Bad Request is returned.

The results are sorted by text score. For more information about the behavior of text search, see MongoDB text search behavior.

Example request:

GET /api/v1/metadata?search=planetmint&limit=2 HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-type: application/json

[
    {
        "metadata": {"msg": "Hello Planetmint 1!"},
        "id": "51ce82a14ca274d43e4992bbce41f6fdeb755f846e48e710a3bbb3b0cf8e4204"
    },
    {
        "metadata": {"msg": "Hello Planetmint 2!"},
        "id": "b4e9005fa494d20e503d916fa87b74fe61c079afccd6e084260674159795ee31"
    },
]
Response Headers
Status Codes
  • 200 OK – The query was executed successfully.

  • 400 Bad Request – The query was not executed successfully. Returned if the text string is empty or the server does not support text search.

Validators

GET /api/v1/validators

Return the local validators set of a given node.

Example request:

GET /api/v1/validators HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-type: application/json

[
    {
        "pub_key": {
               "data":"4E2685D9016126864733225BE00F005515200727FBAB1312FC78C8B76831255A",
               "type":"ed25519"
        },
        "power": 10
    },
    {
         "pub_key": {
               "data":"608D839D7100466D6BA6BE79C320F8B81DE93CFAA58CF9768CF921C6371F2553",
               "type":"ed25519"
         },
         "power": 5
    }
]
Response Headers
Status Codes
  • 200 OK – The query was executed successfully and validators set was returned.

Blocks

GET /api/v1/blocks/{block_height}

Get the block with the height block_height.

Parameters
  • block_height (integer) – block height

Example request:

GET /api/v1/blocks/1 HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "height": 1,
  "transactions": [
    {
      "asset": {
        "data": {
          "msg": "Hello Planetmint!"
        }
      },
      "id": "6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2",
      "inputs": [
        {
          "fulfillment": "pGSAIDE5i63cn4X8T8N1sZ2mGkJD5lNRnBM4PZgI_zvzbr-cgUBcdRj6EnG3MPl47m3XPd1HNfe7q3WL4T6MewNNnat33UvzVnPHo_vossv57M7L064VwrYMLGp097H7IeHpDngK",
          "fulfills": null,
          "owners_before": [
            "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
          ]
        }
      ],
      "metadata": {
        "sequence": 0
      },
      "operation": "CREATE",
      "outputs": [
        {
          "amount": "1",
          "condition": {
            "details": {
              "public_key": "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD",
              "type": "ed25519-sha-256"
            },
            "uri": "ni:///sha-256;PNYwdxaRaNw60N6LDFzOWO97b8tJeragczakL8PrAPc?fpt=ed25519-sha-256&cost=131072"
          },
          "public_keys": [
            "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
          ]
        }
      ],
      "version": "2.0"
    }
  ]
}
Response Headers
Status Codes
  • 200 OK – A block with that block height was found.

  • 400 Bad Request – The request wasn’t understood by the server, e.g. just requesting /blocks without the block_height.

  • 404 Not Found – A block with that block height was not found.

GET /api/v1/blocks

The unfiltered /blocks endpoint without any query parameters returns a 400 Bad Request status code.

Example request:

GET /api/v1/blocks HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 400 Bad Request
Status Codes
  • 400 Bad Request – The request wasn’t understood by the server, e.g. just requesting /blocks without the block_height.

GET /api/v1/blocks?transaction_id={transaction_id}

Retrieve a list of block IDs (block heights), such that the blocks with those IDs contain a transaction with the ID transaction_id. A correct response may consist of an empty list or a list with one block ID.

Note

In case no block was found, an empty list and an HTTP status code 200 OK is returned, as the request was still successful.

Query Parameters
  • transaction_id (string) – (Required) transaction ID

Example request:

GET /api/v1/blocks?transaction_id=6438c733f53dff60bdeded80e8c95126dd3a7ce8c1ee5d5591d030e61cde35d2 HTTP/1.1
Host: example.com

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
  1
]
Response Headers
Status Codes
  • 200 OK – The request was properly formed and zero or more blocks were found containing the specified transaction_id.

  • 400 Bad Request – The request wasn’t understood by the server, e.g. just requesting /blocks, without defining transaction_id.

Determining the API Root URL

When you start Planetmint Server using planetmint start, an HTTP API is exposed at some address. The default is:

http://localhost:9984/api/v1/

It’s bound to localhost, so you can access it from the same machine, but it won’t be directly accessible from the outside world. (The outside world could connect via a SOCKS proxy or whatnot.)

The documentation about Planetmint Server Configuration Settings has a section about how to set server.bind so as to make the HTTP API publicly accessible.

If the API endpoint is publicly accessible, then the public API Root URL is determined as follows:

  • The public IP address (like 12.34.56.78) is the public IP address of the machine exposing the HTTP API to the public internet (e.g. either the machine hosting Gunicorn or the machine running the reverse proxy such as NGINX). It’s determined by AWS, Azure, Rackspace, or whoever is hosting the machine.

  • The DNS hostname (like example.com) is determined by DNS records, such as an “A Record” associating example.com with 12.34.56.78

  • The port (like 9984) is determined by the server.bind setting if Gunicorn is exposed directly to the public Internet. If a reverse proxy (like NGINX) is exposed directly to the public Internet instead, then it could expose the HTTP API on whatever port it wants to. (It should expose the HTTP API on port 9984, but it’s not bound to do that by anything other than convention.)

WebSocket Event Stream API

Important

The WebSocket Event Stream runs on a different port than the Web API. The default port for the Web API is 9984, while the one for the Event Stream is 9985.

Planetmint provides real-time event streams over the WebSocket protocol with the Event Stream API. Connecting to an event stream from your application enables a Planetmint node to notify you as events occur, such as new valid transactions.

Demoing the API

You may be interested in demoing the Event Stream API with the WebSocket echo test to familiarize yourself before attempting an integration.

Determining Support for the Event Stream API

It’s a good idea to make sure that the node you’re connecting with has advertised support for the Event Stream API. To do so, send a HTTP GET request to the node’s API root endpoint (e.g. http://localhost:9984/api/v1/) and check that the response contains a streams property:

{
 ...,
 "streams": "ws://example.com:9985/api/v1/streams/valid_transactions",
 ...
}

Connection Keep-Alive

The Event Stream API supports Ping/Pong frames as descibed in RFC 6455.

Note

It might not be possible to send PING/PONG frames via web browsers because of non availability of Javascript API on different browsers to achieve the same.

Streams

Each stream is meant as a unidirectional communication channel, where the Planetmint node is the only party sending messages. Any messages sent to the Planetmint node will be ignored.

Streams will always be under the WebSocket protocol (so ws:// or wss://) and accessible as extensions to the /api/v<version>/streams/ API root URL (for example, valid transactions would be accessible under /api/v1/streams/valid_transactions). If you’re running your own Planetmint instance and need help determining its root URL, then see the page titled Determining the API Root URL.

All messages sent in a stream are in the JSON format.

Note

For simplicity, Planetmint initially only provides a stream for all committed transactions. In the future, we may provide streams for other information. We may also provide the ability to filter the stream for specific qualities, such as a specific output’s public_key.

If you have specific use cases that you think would fit as part of this API, consider creating a new BEP.

Valid Transactions

/valid_transactions

Streams an event for any newly valid transactions committed to a block. Message bodies contain the transaction’s ID, associated asset ID, and containing block’s height.

Example message:

{
    "transaction_id": "<sha3-256 hash>",
    "asset_id": "<sha3-256 hash>",
    "height": <int>
}

Note

Transactions in Planetmint are committed in batches (“blocks”) and will, therefore, be streamed in batches.

Database Queries

A node operator can use the full power of MongoDB’s query engine to search and query all stored data, including all transactions, assets and metadata. The node operator can decide for themselves how much of that query power they expose to external users.

Querying MongoDB

We wrote a blog post in The Planetmint Blog to show how to use some MongoDB tools to query a Planetmint node’s MongoDB database. It includes some specific example queries for data about custom cars and their ownership histories. Check it out.

How to Connect to MongoDB

Before you can query a MongoDB database, you must connect to it, and to do that, you need to know its hostname and port.

If you’re running a Planetmint node on your local machine (e.g. for dev and test), then the hostname should be localhost and the port should be 27017, unless you did something to change those values. If you’re running a Planetmint node on a remote machine and you can SSH to that machine, then the same is true.

If you’re running a Planetmint node on a remote machine and you configured its MongoDB to use auth and to be publicly-accessible (to people with authorization), then you can probably figure out its hostname and port.

How to Query

A Planetmint node operator has full access to their local MongoDB instance, so they can use any of MongoDB’s APIs for running queries, including:

Note

It’s possible to do query a MongoDB database using SQL. For example:

For example, if you’re on a machine that’s running a default Planetmint node, then you can connect to it using the Mongo Shell (mongo) and look around like so:

$ mongo
MongoDB shell version v3.6.5
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.4
...
> show dbs
admin     0.000GB
planetmint  0.000GB
config    0.000GB
local     0.000GB
> use planetmint
switched to db planetmint
> show collections
abci_chains
assets
blocks
elections
metadata
pre_commit
transactions
utxos
validators

The above example illustrates several things:

  • When you don’t specify the hostname or port, the Mongo Shell assumes they are localhost and 27017, respectively. (localhost had IP address 127.0.0.1 on the machine in question, an Ubuntu machine.)

  • Planetmint stores its data in a database named planetmint.

  • The planetmint database contains several collections.

  • Votes aren’t stored in any collection, currently. They are all handled and stored by Tendermint in its own (LevelDB) database.

Example Documents from Some Collections

The most interesting collections in the planetmint database are:

  • transactions

  • assets

  • metadata

  • blocks

You can explore those collections using MongoDB queries such as db.assets.findOne(). We now show some example documents from each of those collections.

Example Documents from transactions

A CREATE transaction from the transactions collection includes an extra "_id" field (added by MongoDB) and is missing its "asset" and "metadata" fields: that data was removed and stored in the assets and metadata collections.

{
    "_id":ObjectId("5b17b9fa6ce88300067b6804"),
    "inputs":[…],
    "outputs":[…],
    "operation":"CREATE",
    "version":"2.0",
    "id":"816c4dd7…851af1629"
}

A TRANSFER transaction from the transactions collection is similar, but it keeps its "asset" field.

{
    "_id":ObjectId("5b17b9fa6ce88300067b6807"),
    "inputs":[…],
    "outputs":[…],
    "operation":"TRANSFER",
    "asset":{
        "id":"816c4dd7ae…51af1629"
    },
    "version":"2.0",
    "id":"985ee697d…a3296b9"
}
Example Document from assets

A document from the assets collection has three top-level fields: an "_id" field added by MongoDB, the asset.data from a CREATE transaction, and the "id" of the CREATE transaction it came from.

{
    "_id":ObjectId("5b17b9fe6ce88300067b6823"),
    "data":{
        "type":"cow",
        "name":"Mildred"
    },
    "id":"96002ef8740…45869959d8"
}
Example Document from metadata

A document from the metadata collection has three top-level fields: an "_id" field added by MongoDB, the metadata from a transaction, and the "id" of the transaction it came from.

{
    "_id":ObjectId("5b17ba006ce88300067b683d"),
    "metadata":{
        "transfer_time":1058568256
    },
    "id":"53cba620e…ae9fdee0"
}
Example Document from blocks
{
    "_id":ObjectId("5b212c1ceaaa420006f41c57"),
    "app_hash":"2b0b75c2c2…7fb2652ce26c6",
    "height":17,
    "transactions":[
        "5f1f2d6b…ed98c1e"
    ]
}

What a Node Operator Can Expose to External Users

Each node operator can decide how they let external users get information from their local MongoDB database. They could expose:

  • their local MonogoDB database itself to queries from external users, maybe as a MongoDB user with a role that has limited privileges, e.g. read-only.

  • a limited HTTP API, allowing a restricted set of predefined queries, such as the HTTP API provided by Planetmint Server, or a custom HTTP API implemented using Django, Express, Ruby on Rails, or ASP.NET.

  • some other API, such as a GraphQL API. They could do that using custom code or code from a third party.

Each node operator can expose a different level or type of access to their local MongoDB database. For example, one node operator might decide to specialize in offering optimized geospatial queries.

Security Considerations

In Planetmint version 1.3.0 and earlier, there was one logical MongoDB database, so exposing that database to external users was very risky, and was not recommended. “Drop database” would delete that one shared MongoDB database.

In Planetmint version 2.0.0 and later, each node has its own isolated local MongoDB database. Inter-node communications are done using Tendermint protocols, not MongoDB protocols, as illustrated in Figure 1 below. If a node’s local MongoDB database gets compromised, none of the other MongoDB databases (in the other nodes) will be affected.

Diagram of a four-node Planetmint 2.0 network

Figure 1: A Four-Node Planetmint 2.0 Network




Performance and Cost Considerations

Query processing can be quite resource-intensive, so it’s a good idea to have MongoDB running in a separate machine from those running Planetmint Server and Tendermint Core.

A node operator might want to measure the resources used by a query, so they can charge whoever requested the query accordingly.

Some queries can take too long or use too many resources. A node operator should put upper bounds on the resources that a query can use, and halt (or prevent) any query that goes over.

To make MongoDB queries more efficient, one can create indexes. Those indexes might be created by the node operator or by some external users (if the node operator allows that). It’s worth noting that indexes aren’t free: whenever new data is appended to a collection, the corresponding indexes must be updated. The node operator might want to pass those costs on to whoever created the index. Moreover, in MongoDB, a single collection can have no more than 64 indexes.

One can create a follower node: a node with Tendermint voting power 0. It would still have a copy of all the data, so it could be used as read-only node. A follower node could offer specialized queries as a service without affecting the workload on the voting validators (which can also write). There could even be followers of followers.

JavaScript Query Code Examples

One can connect to a node’s MongoDB database using any of the MongoDB drivers, such as the MongoDB Node.js driver. Here are some links to example JavaScript code that queries a Planetmint node’s MongoDB database: