mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Merge pull request #830 from bigchaindb/docs/601/design-http-api
es[WIP/Feedback] Design BigchainDB HTTP API v0.9
This commit is contained in:
commit
34d1a329ca
@ -4,13 +4,61 @@ import json
|
||||
import os
|
||||
import os.path
|
||||
|
||||
from bigchaindb.common.transaction import Transaction
|
||||
from bigchaindb.common.transaction import Transaction, Input, TransactionLink
|
||||
from bigchaindb.core import Bigchain
|
||||
from bigchaindb.models import Block
|
||||
from bigchaindb.web import server
|
||||
|
||||
|
||||
TPLS = {}
|
||||
|
||||
|
||||
TPLS['index-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
%(index)s
|
||||
"""
|
||||
|
||||
TPLS['api-index-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
%(api_index)s
|
||||
"""
|
||||
|
||||
TPLS['get-tx-id-request'] = """\
|
||||
GET /api/v1/transactions/%(txid)s HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-tx-id-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
%(tx)s
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-tx-by-asset-request'] = """\
|
||||
GET /api/v1/transactions?operation=TRANSFER&asset_id=%(txid)s HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-tx-by-asset-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
[%(tx_transfer)s,
|
||||
%(tx_transfer_last)s]
|
||||
"""
|
||||
|
||||
TPLS['post-tx-request'] = """\
|
||||
POST /transactions/ HTTP/1.1
|
||||
POST /api/v1/transactions/ HTTP/1.1
|
||||
Host: example.com
|
||||
Content-Type: application/json
|
||||
|
||||
@ -19,62 +67,214 @@ Content-Type: application/json
|
||||
|
||||
|
||||
TPLS['post-tx-response'] = """\
|
||||
HTTP/1.1 201 Created
|
||||
HTTP/1.1 202 Accepted
|
||||
Content-Type: application/json
|
||||
|
||||
%(tx)s
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-tx-status-request'] = """\
|
||||
GET /transactions/%(txid)s/status HTTP/1.1
|
||||
TPLS['get-statuses-tx-request'] = """\
|
||||
GET /statuses?tx_id=%(txid)s HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-tx-status-response'] = """\
|
||||
TPLS['get-statuses-tx-invalid-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "valid"
|
||||
"status": "invalid"
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-tx-request'] = """\
|
||||
GET /transactions/%(txid)s HTTP/1.1
|
||||
TPLS['get-statuses-tx-valid-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "valid",
|
||||
"_links": {
|
||||
"tx": "/transactions/%(txid)s"
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-statuses-block-request'] = """\
|
||||
GET /api/v1/statuses?block_id=%(blockid)s HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-tx-response'] = """\
|
||||
TPLS['get-statuses-block-invalid-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
%(tx)s
|
||||
{
|
||||
"status": "invalid"
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-statuses-block-valid-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "valid",
|
||||
"_links": {
|
||||
"block": "/blocks/%(blockid)s"
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-block-request'] = """\
|
||||
GET /api/v1/blocks/%(blockid)s HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-block-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
%(block)s
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-block-txid-request'] = """\
|
||||
GET /api/v1/blocks?tx_id=%(txid)s HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-block-txid-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
%(block_list)s
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-vote-request'] = """\
|
||||
GET /api/v1/votes?block_id=%(blockid)s HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
"""
|
||||
|
||||
|
||||
TPLS['get-vote-response'] = """\
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
[%(vote)s]
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
""" Main function """
|
||||
|
||||
ctx = {}
|
||||
|
||||
def pretty_json(data):
|
||||
return json.dumps(data, indent=2, sort_keys=True)
|
||||
|
||||
client = server.create_app().test_client()
|
||||
|
||||
host = 'example.com:9984'
|
||||
|
||||
# HTTP Index
|
||||
res = client.get('/', environ_overrides={'HTTP_HOST': host})
|
||||
res_data = json.loads(res.data.decode())
|
||||
res_data['keyring'] = [
|
||||
"6qHyZew94NMmUTYyHnkZsB8cxJYuRNEiEpXHe1ih9QX3",
|
||||
"AdDuyrTyjrDt935YnFu4VBCVDhHtY2Y6rcy7x2TFeiRi"
|
||||
]
|
||||
ctx['index'] = pretty_json(res_data)
|
||||
|
||||
# API index
|
||||
res = client.get('/api/v1/', environ_overrides={'HTTP_HOST': host})
|
||||
ctx['api_index'] = pretty_json(json.loads(res.data.decode()))
|
||||
|
||||
# tx create
|
||||
privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z'
|
||||
pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD'
|
||||
tx = Transaction.create([pubkey], [([pubkey], 1)])
|
||||
asset = {'msg': 'Hello BigchainDB!'}
|
||||
tx = Transaction.create([pubkey], [([pubkey], 1)], asset=asset, metadata={'sequence': 0})
|
||||
tx = tx.sign([privkey])
|
||||
tx_json = json.dumps(tx.to_dict(), indent=2, sort_keys=True)
|
||||
ctx['tx'] = pretty_json(tx.to_dict())
|
||||
ctx['public_keys'] = tx.outputs[0].public_keys[0]
|
||||
ctx['txid'] = tx.id
|
||||
|
||||
# tx transfer
|
||||
privkey_transfer = '3AeWpPdhEZzWLYfkfYHBfMFC2r1f8HEaGS9NtbbKssya'
|
||||
pubkey_transfer = '3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9'
|
||||
|
||||
cid = 0
|
||||
input_ = Input(fulfillment=tx.outputs[cid].fulfillment,
|
||||
fulfills=TransactionLink(txid=tx.id, output=cid),
|
||||
owners_before=tx.outputs[cid].public_keys)
|
||||
tx_transfer = Transaction.transfer([input_], [([pubkey_transfer], 1)], asset_id=tx.id, metadata={'sequence': 1})
|
||||
tx_transfer = tx_transfer.sign([privkey])
|
||||
ctx['tx_transfer'] = pretty_json(tx_transfer.to_dict())
|
||||
ctx['public_keys_transfer'] = tx_transfer.outputs[0].public_keys[0]
|
||||
ctx['tx_transfer_id'] = tx_transfer.id
|
||||
|
||||
# privkey_transfer_last = 'sG3jWDtdTXUidBJK53ucSTrosktG616U3tQHBk81eQe'
|
||||
pubkey_transfer_last = '3Af3fhhjU6d9WecEM9Uw5hfom9kNEwE7YuDWdqAUssqm'
|
||||
|
||||
cid = 0
|
||||
input_ = Input(fulfillment=tx_transfer.outputs[cid].fulfillment,
|
||||
fulfills=TransactionLink(txid=tx_transfer.id, output=cid),
|
||||
owners_before=tx_transfer.outputs[cid].public_keys)
|
||||
tx_transfer_last = Transaction.transfer([input_], [([pubkey_transfer_last], 1)],
|
||||
asset_id=tx.id, metadata={'sequence': 2})
|
||||
tx_transfer_last = tx_transfer_last.sign([privkey_transfer])
|
||||
ctx['tx_transfer_last'] = pretty_json(tx_transfer_last.to_dict())
|
||||
ctx['tx_transfer_last_id'] = tx_transfer_last.id
|
||||
ctx['public_keys_transfer_last'] = tx_transfer_last.outputs[0].public_keys[0]
|
||||
|
||||
# block
|
||||
node_private = "5G2kE1zJAgTajkVSbPAQWo4c2izvtwqaNHYsaNpbbvxX"
|
||||
node_public = "DngBurxfeNVKZWCEcDnLj1eMPAS7focUZTE5FndFGuHT"
|
||||
signature = "53wxrEQDYk1dXzmvNSytbCfmNVnPqPkDQaTnAe8Jf43s6ssejPxezkCvUnGTnduNUmaLjhaan1iRLi3peu6s5DzA"
|
||||
block = Block(transactions=[tx], node_pubkey=node_public, voters=[node_public], signature=signature)
|
||||
ctx['block'] = pretty_json(block.to_dict())
|
||||
ctx['blockid'] = block.id
|
||||
|
||||
block_transfer = Block(transactions=[tx_transfer], node_pubkey=node_public,
|
||||
voters=[node_public], signature=signature)
|
||||
ctx['block_transfer'] = pretty_json(block.to_dict())
|
||||
|
||||
# vote
|
||||
DUMMY_SHA3 = '0123456789abcdef' * 4
|
||||
b = Bigchain(public_key=node_public, private_key=node_private)
|
||||
vote = b.vote(block.id, DUMMY_SHA3, True)
|
||||
ctx['vote'] = pretty_json(vote)
|
||||
|
||||
# block status
|
||||
block_list = [
|
||||
block_transfer.id,
|
||||
block.id
|
||||
]
|
||||
ctx['block_list'] = pretty_json(block_list)
|
||||
|
||||
base_path = os.path.join(os.path.dirname(__file__),
|
||||
'source/drivers-clients/samples')
|
||||
|
||||
if not os.path.exists(base_path):
|
||||
os.makedirs(base_path)
|
||||
|
||||
for name, tpl in TPLS.items():
|
||||
path = os.path.join(base_path, name + '.http')
|
||||
code = tpl % {'tx': tx_json, 'txid': tx.id}
|
||||
code = tpl % ctx
|
||||
with open(path, 'w') as handle:
|
||||
handle.write(code)
|
||||
|
||||
|
@ -1,58 +1,136 @@
|
||||
The HTTP Client-Server API
|
||||
==========================
|
||||
|
||||
.. note::
|
||||
|
||||
The HTTP client-server API is currently quite rudimentary. For example,
|
||||
there is no ability to do complex queries using the HTTP API. We plan to add
|
||||
more querying capabilities in the future.
|
||||
|
||||
This page assumes you already know an API Root URL
|
||||
for a BigchainDB node or reverse proxy.
|
||||
It should be something like ``http://apihosting4u.net:9984``
|
||||
or ``http://12.34.56.78:9984``.
|
||||
It should be something like ``https://example.com:9984``
|
||||
or ``https://12.34.56.78:9984``.
|
||||
|
||||
If you set up a BigchainDB 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.
|
||||
|
||||
|
||||
API Root URL
|
||||
------------
|
||||
BigchainDB Root URL
|
||||
-------------------
|
||||
|
||||
If you send an HTTP GET request to the API Root URL
|
||||
If you send an HTTP GET request to the BigchainDB Root URL
|
||||
e.g. ``http://localhost:9984``
|
||||
or ``http://apihosting4u.net: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:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"keyring": [
|
||||
"6qHyZew94NMmUTYyHnkZsB8cxJYuRNEiEpXHe1ih9QX3",
|
||||
"AdDuyrTyjrDt935YnFu4VBCVDhHtY2Y6rcy7x2TFeiRi"
|
||||
],
|
||||
"public_key": "AiygKSRhZWTxxYT4AfgKoTG4TZAoPsWoEt6C6bLq4jJR",
|
||||
"software": "BigchainDB",
|
||||
"version": "0.6.0"
|
||||
}
|
||||
.. literalinclude:: samples/index-response.http
|
||||
:language: http
|
||||
|
||||
|
||||
POST /transactions/
|
||||
API Root Endpoint
|
||||
-------------------
|
||||
|
||||
.. http:post:: /transactions/
|
||||
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 BigchainDB API endpoints:
|
||||
|
||||
.. literalinclude:: samples/api-index-response.http
|
||||
:language: http
|
||||
|
||||
|
||||
Transactions
|
||||
-------------------
|
||||
|
||||
.. http:get:: /api/v1/transactions/{tx_id}
|
||||
|
||||
Get the transaction with the ID ``tx_id``.
|
||||
|
||||
This endpoint returns a transaction only if a ``VALID`` block on
|
||||
``bigchain`` exists.
|
||||
|
||||
:param tx_id: transaction ID
|
||||
:type tx_id: hex string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-tx-id-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-tx-id-response.http
|
||||
:language: http
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
|
||||
:statuscode 200: A transaction with that ID was found.
|
||||
:statuscode 404: A transaction with that ID was not found.
|
||||
|
||||
.. http:get:: /api/v1/transactions
|
||||
|
||||
The unfiltered ``/api/v1/transactions`` endpoint without any query parameters
|
||||
returns a status code `400`. For valid filters, see the sections below.
|
||||
|
||||
There are however filtered requests that might come of use, given the endpoint is
|
||||
queried correctly. Some of them include retrieving a list of transactions
|
||||
that include:
|
||||
|
||||
* `Transactions related to a specific asset <#get--transactions?asset_id=asset_id&operation=CREATE|TRANSFER>`_
|
||||
|
||||
In this section, we've listed those particular requests, as they will likely
|
||||
to be very handy when implementing your application on top of BigchainDB.
|
||||
|
||||
.. note::
|
||||
Looking up transactions with a specific ``metadata`` field is currently not supported,
|
||||
however, providing a way to query based on ``metadata`` data is on our roadmap.
|
||||
|
||||
A generalization of those parameters follows:
|
||||
|
||||
:query string asset_id: The ID of the asset.
|
||||
|
||||
:query string operation: (Optional) One of the two supported operations of a transaction: ``CREATE``, ``TRANSFER``.
|
||||
|
||||
.. http:get:: /api/v1/transactions?asset_id={asset_id}&operation={CREATE|TRANSFER}
|
||||
|
||||
Get a list of transactions that use an asset with the ID ``asset_id``.
|
||||
Every ``TRANSFER`` transaction that originates from a ``CREATE`` transaction
|
||||
with ``asset_id`` will be included. This allows users to query the entire history or
|
||||
provenance of an asset.
|
||||
|
||||
This endpoint returns transactions only if they are decided ``VALID`` by the server.
|
||||
|
||||
:query string operation: (Optional) One of the two supported operations of a transaction: ``CREATE``, ``TRANSFER``.
|
||||
|
||||
:query string asset_id: asset ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-tx-by-asset-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-tx-by-asset-response.http
|
||||
:language: http
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
|
||||
:statuscode 200: A list of transactions containing an asset with ID ``asset_id`` was found and returned.
|
||||
:statuscode 400: The request wasn't understood by the server, e.g. the ``asset_id`` querystring was not included in the request.
|
||||
|
||||
|
||||
.. http:post:: /api/v1/transactions
|
||||
|
||||
Push a new transaction.
|
||||
|
||||
Note: The posted transaction should be a valid and signed :doc:`transaction <../data-models/transaction-model>`.
|
||||
The steps to build a valid transaction are beyond the scope of this page.
|
||||
One would normally use a driver such as the `BigchainDB Python Driver
|
||||
<https://docs.bigchaindb.com/projects/py-driver/en/latest/index.html>`_ to
|
||||
build a valid transaction. The exact contents of a valid transaction depend
|
||||
on the associated public/private keypairs.
|
||||
.. note::
|
||||
The posted `transaction
|
||||
<https://docs.bigchaindb.com/projects/server/en/latest/data-models/transaction-model.html>`_
|
||||
should be structurally valid and not spending an already spent output.
|
||||
The steps to build a valid transaction are beyond the scope of this page.
|
||||
One would normally use a driver such as the `BigchainDB Python Driver
|
||||
<https://docs.bigchaindb.com/projects/py-driver/en/latest/index.html>`_
|
||||
to build a valid transaction.
|
||||
|
||||
**Example request**:
|
||||
|
||||
@ -64,110 +142,255 @@ POST /transactions/
|
||||
.. literalinclude:: samples/post-tx-response.http
|
||||
:language: http
|
||||
|
||||
:statuscode 201: A new transaction was created.
|
||||
:statuscode 400: The transaction was invalid and not created.
|
||||
:resheader Content-Type: ``application/json``
|
||||
|
||||
:statuscode 202: The pushed transaction was accepted in the ``BACKLOG``, but the processing has not been completed.
|
||||
:statuscode 400: The transaction was malformed and not accepted in the ``BACKLOG``.
|
||||
|
||||
|
||||
GET /transactions/{tx_id}/status
|
||||
--------------------------------
|
||||
Transaction Outputs
|
||||
-------------------
|
||||
|
||||
.. http:get:: /transactions/{tx_id}/status
|
||||
|
||||
Get the status of the transaction with the ID ``tx_id``, if a transaction
|
||||
with that ``tx_id`` exists.
|
||||
|
||||
The possible status values are ``backlog``, ``undecided``, ``valid`` or
|
||||
``invalid``.
|
||||
|
||||
:param tx_id: transaction ID
|
||||
:type tx_id: hex string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-tx-status-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-tx-status-response.http
|
||||
:language: http
|
||||
|
||||
:statuscode 200: A transaction with that ID was found and the status is returned.
|
||||
:statuscode 404: A transaction with that ID was not found.
|
||||
The ``/api/v1/outputs`` endpoint returns transactions outputs filtered by a
|
||||
given public key, and optionally filtered to only include outputs that have
|
||||
not already been spent.
|
||||
|
||||
|
||||
GET /transactions/{tx_id}
|
||||
-------------------------
|
||||
.. http:get:: /api/v1/outputs?public_key={public_key}
|
||||
|
||||
.. http:get:: /transactions/{tx_id}
|
||||
Get transaction outputs by public key. The `public_key` parameter must be
|
||||
a base58 encoded ed25519 public key associated with transaction output
|
||||
ownership.
|
||||
|
||||
Get the transaction with the ID ``tx_id``.
|
||||
Returns a list of links to transaction outputs.
|
||||
|
||||
This endpoint returns only a transaction from a ``VALID`` or ``UNDECIDED``
|
||||
block on ``bigchain``, if exists.
|
||||
:param 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.
|
||||
:param unspent: Boolean value ("true" or "false") indicating if the result set should be limited to outputs that are available to spend.
|
||||
|
||||
:param tx_id: transaction ID
|
||||
:type tx_id: hex string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-tx-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-tx-response.http
|
||||
:language: http
|
||||
|
||||
:statuscode 200: A transaction with that ID was found.
|
||||
:statuscode 404: A transaction with that ID was not found.
|
||||
|
||||
|
||||
GET /unspents/
|
||||
-------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
This endpoint (unspents) is not yet implemented. We published it here for preview and comment.
|
||||
|
||||
|
||||
.. http:get:: /unspents?owner_after={owner_after}
|
||||
|
||||
Get a list of links to transactions' outputs that have not been used in
|
||||
a previous transaction and could hence be called unspent outputs
|
||||
(or simply: unspents).
|
||||
|
||||
This endpoint will return a ``HTTP 400 Bad Request`` if the querystring
|
||||
``owner_after`` happens to not be defined in the request.
|
||||
|
||||
Note that if unspents for a certain ``public_key`` have not been found by
|
||||
the server, this will result in the server returning a 200 OK HTTP status
|
||||
code and an empty list in the response's body.
|
||||
|
||||
:param owner_after: A public key, able to validly spend an output of a transaction, assuming the user also has the corresponding private key.
|
||||
:type owner_after: base58 encoded string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /unspents?owner_after=1AAAbbb...ccc HTTP/1.1
|
||||
GET /api/v1/outputs?public_key=1AAAbbb...ccc HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
[
|
||||
"../transactions/2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e/outputs/0",
|
||||
"../transactions/2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e/outputs/1"
|
||||
]
|
||||
|
||||
:statuscode 200: A list of outputs were found and returned in the body of the response.
|
||||
:statuscode 400: The request wasn't understood by the server, e.g. the ``public_key`` querystring was not included in the request.
|
||||
|
||||
|
||||
Statuses
|
||||
--------------------------------
|
||||
|
||||
.. http:get:: /api/v1/statuses
|
||||
|
||||
Get the status of an asynchronously written transaction or block by their id.
|
||||
|
||||
A link to the resource is also provided in the returned payload under
|
||||
``_links``.
|
||||
|
||||
:query string tx_id: transaction ID
|
||||
:query string block_id: block ID
|
||||
|
||||
.. note::
|
||||
|
||||
Exactly one of the ``tx_id`` or ``block_id`` query parameters must be
|
||||
used together with this endpoint (see below for getting `transaction
|
||||
statuses <#get--statuses?tx_id=tx_id>`_ and `block statuses
|
||||
<#get--statuses?block_id=block_id>`_).
|
||||
|
||||
|
||||
.. http:get:: /api/v1/statuses?tx_id={tx_id}
|
||||
|
||||
Get the status of a transaction.
|
||||
|
||||
The possible status values are ``undecided``, ``valid`` or ``backlog``.
|
||||
If a transaction in neither of those states is found, a ``404 Not Found``
|
||||
HTTP status code is returned. `We're currently looking into ways to unambigously let the user know about a transaction's status that was included in an invalid block. <https://github.com/bigchaindb/bigchaindb/issues/1039>`_
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-statuses-tx-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-statuses-tx-valid-response.http
|
||||
:language: http
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
:resheader Location: Once the transaction has been persisted, this header will link to the actual resource.
|
||||
|
||||
:statuscode 200: A transaction with that ID was found.
|
||||
:statuscode 404: A transaction with that ID was not found.
|
||||
|
||||
|
||||
.. http:get:: /api/v1/statuses?block_id={block_id}
|
||||
|
||||
Get the status of a block.
|
||||
|
||||
The possible status values are ``undecided``, ``valid`` or ``invalid``.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-statuses-block-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-statuses-block-invalid-response.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-statuses-block-valid-response.http
|
||||
:language: http
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
:resheader Location: Once the block has been persisted, this header will link to the actual resource.
|
||||
|
||||
:statuscode 200: A block with that ID was found.
|
||||
:statuscode 404: A block with that ID was not found.
|
||||
|
||||
|
||||
Advanced Usage
|
||||
--------------------------------
|
||||
|
||||
The following endpoints are more advanced and meant for debugging and transparency purposes.
|
||||
|
||||
More precisely, the `blocks endpoint <#blocks>`_ allows you to retrieve a block by ``block_id`` as well the list of blocks that
|
||||
a certain transaction with ``tx_id`` occured in (a transaction can occur in multiple ``invalid`` blocks until it
|
||||
either gets rejected or validated by the system). This endpoint gives the ability to drill down on the lifecycle of a
|
||||
transaction
|
||||
|
||||
The `votes endpoint <#votes>`_ contains all the voting information for a specific block. So after retrieving the
|
||||
``block_id`` for a given ``tx_id``, one can now simply inspect the votes that happened at a specific time on that block.
|
||||
|
||||
|
||||
Blocks
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. http:get:: /api/v1/blocks/{block_id}
|
||||
|
||||
Get the block with the ID ``block_id``. Any blocks, be they ``VALID``, ``UNDECIDED`` or ``INVALID`` will be
|
||||
returned. To check a block's status independently, use the `Statuses endpoint <#status>`_.
|
||||
To check the votes on a block, have a look at the `votes endpoint <#votes>`_.
|
||||
|
||||
:param block_id: block ID
|
||||
:type block_id: hex string
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-block-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-block-response.http
|
||||
:language: http
|
||||
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
|
||||
:statuscode 200: A block with that ID was found.
|
||||
:statuscode 400: The request wasn't understood by the server, e.g. just requesting ``/blocks`` without the ``block_id``.
|
||||
:statuscode 404: A block with that ID was not found.
|
||||
|
||||
|
||||
.. http:get:: /api/v1/blocks
|
||||
|
||||
The unfiltered ``/blocks`` endpoint without any query parameters returns a `400` status code.
|
||||
The list endpoint should be filtered with a ``tx_id`` query parameter,
|
||||
see the ``/blocks?tx_id={tx_id}&status={UNDECIDED|VALID|INVALID}``
|
||||
`endpoint <#get--blocks?tx_id=tx_id&status=UNDECIDED|VALID|INVALID>`_.
|
||||
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/blocks HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
HTTP/1.1 400 Bad Request
|
||||
|
||||
[
|
||||
"../transactions/2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e/outputs/0",
|
||||
"../transactions/2d431073e1477f3073a4693ac7ff9be5634751de1b8abaa1f4e19548ef0b4b0e/outputs/1"
|
||||
]
|
||||
:statuscode 400: The request wasn't understood by the server, e.g. just requesting ``/blocks`` without the ``block_id``.
|
||||
|
||||
:statuscode 200: A list of outputs were found and returned in the body of the response.
|
||||
:statuscode 400: The request wasn't understood by the server, e.g. the ``owner_after`` querystring was not included in the request.
|
||||
.. http:get:: /api/v1/blocks?tx_id={tx_id}&status={UNDECIDED|VALID|INVALID}
|
||||
|
||||
Retrieve a list of ``block_id`` with their corresponding status that contain a transaction with the ID ``tx_id``.
|
||||
|
||||
Any blocks, be they ``UNDECIDED``, ``VALID`` or ``INVALID`` will be
|
||||
returned if no status filter is provided.
|
||||
|
||||
.. 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 string tx_id: transaction ID *(required)*
|
||||
:query string status: Filter blocks by their status. One of ``VALID``, ``UNDECIDED`` or ``INVALID``.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-block-txid-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-block-txid-response.http
|
||||
:language: http
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
|
||||
:statuscode 200: A list of blocks containing a transaction with ID ``tx_id`` was found and returned.
|
||||
:statuscode 400: The request wasn't understood by the server, e.g. just requesting ``/blocks``, without defining ``tx_id``.
|
||||
|
||||
|
||||
Votes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. http:get:: /api/v1/votes?block_id={block_id}
|
||||
|
||||
Retrieve a list of votes for a certain block with ID ``block_id``.
|
||||
To check for the validity of a vote, a user of this endpoint needs to
|
||||
perform the `following steps: <https://github.com/bigchaindb/bigchaindb/blob/8ebd93ed3273e983f5770b1617292aadf9f1462b/bigchaindb/util.py#L119>`_
|
||||
|
||||
1. Check if the vote's ``node_pubkey`` is allowed to vote.
|
||||
2. Verify the vote's signature against the vote's body (``vote.vote``) and ``node_pubkey``.
|
||||
|
||||
|
||||
:query string block_id: The block ID to filter the votes.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. literalinclude:: samples/get-vote-request.http
|
||||
:language: http
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. literalinclude:: samples/get-vote-response.http
|
||||
:language: http
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
|
||||
:statuscode 200: A list of votes voting for a block with ID ``block_id`` was found and returned.
|
||||
:statuscode 400: The request wasn't understood by the server, e.g. just requesting ``/votes``, without defining ``block_id``.
|
||||
|
||||
|
||||
Determining the API Root URL
|
||||
@ -196,8 +419,8 @@ then the public API Root URL is determined as follows:
|
||||
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 apihosting4u.net) is determined by DNS records,
|
||||
such as an "A Record" associating apihosting4u.net with 12.34.56.78
|
||||
- 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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user