We designed the endpoints around the frequent needs and pain points of building an Ethereum-powered project. We give you access to the data you need, exactly how you need it - through a comprehensive, general-purpose data model based on EthOn with meaningful aggregation and filtering capabilities exposed via query parameters.

Here are only a few examples that illustrate the power of the API - these use cases are typically not supported by the standard Ethereum json-rpc interface:

Response format

All API responses are serialized as JSON objects and follow the conventions of the JSON:API specificaton:

If the response object has a data property, the request was successful and the value of the data property can be either a single object (representing a Resource) or an array of objects (representing a Collection).

Otherwise, the response object will have a single errors property, whose value is an array of Error objects.

The meta object

All succesful responses include a meta property along with the data property in the response object. The meta object includes helper information that can vary depending on the type of request and will be described along with the relevant functionality (e.g. the sections on Pagination and Reorg Handling).

For all API responses, however, the meta object includes a few details about the latest block of the canonical chain, as it is seen by the API at the time of the request. This can serve as an anchor for queries that ask for the most recent items of a collection (e.g. latest transactions for an account), as it defines what 'most recent' means to the API at the time of the request:

Along with the identifier data, all resources have two other types of properties:

attributes are static values specific to the resource

relationships are pointers to other (related) resources or collections

For example, the genesis block has:

{"attributes":{"number":0,"blockCreationTime":1438226773// ... other attibutes},"relationships":{"hasBeneficiary":{// pointer to the miner's Account},"transactions":{// pointer to the collection of Transactions}}}

Relationships and Links

All the blockchain resources are part a large graph of interconnected concepts. The API is translating these connections into resource relationships. There are two types of relationships:

A to-one relationship is a link to a single other resource (e.g. there's a single from Account for any Transaction).

A to-many relationship is a link to a collection of resources sharing the same type (e.g. there is a collection of Transactions for any given Block).

Both the to-one and to-many relationships are represented by a fully-formed URL called the related link. According to the JSON:API specificaton this will be serialized as:

Note: In practice, the related links will be normalized to include the canonical identifier of the origin.
Instead of /blocks/genesis/... (we used this in the examples above for brevity) the related links will read /blocks/0xd4e56740.../....

Multi-Resource Queries

Sometimes it's helpful to fetch a bundle of related resources with a single API request. The API enables you to do this via the include URL parameter.
You can choose to include any subset of to-one relationships by providing a comma-separated list of the relationship names in the request.

Let's explore the first Ethereum transaction, along with the details of its from and to Accounts:

Note the trailing include=from,to argument in the URL. This asks the API to append the related resources to the response, grouped under the included key:

{"data":{"type":"Transaction","id":"0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060","relationships":{"from":{"data":{"type":"Account","id":"0xa1e4380a3b1f749673e270229993ee55f35663b4"}// "links" not relevant for this example},"to":{"data":{"type":"Account","id":"0x5df9b87991262f6ba471f09758cde1c0fc1de734"}// "links" not relevant for this example}}// ... other Transaction details},"included":[{"type":"Account","id":"0xa1e4380a3b1f749673e270229993ee55f35663b4",// ... other Account details},{"type":"Account","id":"0x5df9b87991262f6ba471f09758cde1c0fc1de734",// ... other Account details}]}

An included resource will be appended to the included array one time, even if it's referenced by more than one relationship (e.g. if the from and the to Accounts would have been identical in the example above, that Account wouldn't be included twice in the array).

Note: Only the to-one relationships can be multiplexed in a single request. All to-many relationships need to be queried explicitly in separate requests. We chose this approach so we could simplify the API query logic for collection pagination and filtering.

Collection ordering

The default sorting order for all resources that directly relate to activity on a timeline (e.g. Blocks, Transactions, ContractMessages, LogEntries) is reverse chronological (most recent entries are first on the list). We chose this approach as most often than not, users are interested primarily in events or transactions that happened recently, rather than the ones that happened a long time ago.

The globalRank attribute, where present, serves as an aid to this ordering criteria, as it aggregates a hierarchy of indexes into a single composite value:

The block number

The index of a message (transaction or contract message) in the context of a block

The index of an event in the context of a transaction

This value allows you to sort heterogeneous collections of items chronologically, according to the relative order in which they were executed.

Filters

Filters can assist you in refining your queries and distilling the data sets down to resources that have certain properties (attributes or relationships).
As a general rule, the filters are applied through the filter[NAME] URL argument. Multiple filters can be chained within a single request, as long as they're targeting different properties.

Example: Let's query the list of transactions between two specific accounts:

Note: All collections of the same resource type have support for the same filtering parameters.

You will find a full list of supported filters for each collection type in the endpoint reference below. Please note that all filters are only listed once for each collection type, although they can be applied on related collections as well.

Pagination

All resource collections that are exported by the API share a uniform pagination strategy.

The maximum number of items on a page is controlled by the page[limit] URL argument. The default value is 10 and the maximum allowed value is 100.

The beginning or end of the requested page is controlled by a cursor value assigned to either the page[next] or page[prev] URL arguments. Each resource has an immutable cursor attribute that can be used for this purpose.

Note: All the resources that are subject to pagination have a reverse chronological default ordering. This can make the pagination language counter-intuitive, unless you think of the items as being part of an 'activity feed' (with the most recent activity shown on the top of the list). Thus, the first (default) page will always start with the most recent items and progress towards older items. The next page will display older items than the current page, whereas the prev page will display more recent items.

The page[next]=cursor argument requests the next page starting immediately after cursor

Notice how links.prev and links.next were generated to include the cursors of the first and the last items in the current page.

Note: The values set for page[limit] (along with any other filter[] applied to the current page) will be preserved in the pagination links for the next and prev pages.

For all paginated collections, the meta object assigned to the response will include a page object that provides information about the items of the next and prev pages:

meta.page.hasNext is a boolean value that indicates whether the next page (starting immediately after the cursor of the last item in the current page) has at least one item.

meta.page.hasPrev is a boolean value that indicates whether the previous page (ending immediately before the cursor of the first item in the current page) has at least one item.

Reorg Handling

Data Latency

Our data pipeline keeps track of the blockchain growth in real-time, so you get access to the most recent activity as soon as it takes place. We don't require you to wait for an arbitrary number of confirmations until you get access to the data, so you can build applications that react as quickly as possible to the on-chain events, with minimal delays for your users.

This is a powerful feature that introduces a subtle layer of complexity due to how distributed consensus works: the miners are competing for producing new blocks and sometimes the latest section of the chain becomes a stale branch because a better branch was produced by other nodes. This is also known as a "chain reorg".

In the image above, the block segment P1-P2 (that was part of the canonical chain) becomes a stale branch because a better chain was created via M1-M2-M3. After the reorg took place, any transaction that was included in P1 or P2 is no longer part of the main chain (hence no longer confirmed), unless it is mined again in one of the blocks that are now part of the main chain.

Rollbacks

We designed the API to handle these situations with minimal overhead for you. The pagination cursors are reorg-safe, so you can surf through resource collections or poll for updates without worrying about data inconsistencies related to reorgs. If we detect that a subset of the items that we've given you have become stale (because the chain reorganized in between requests), we'll simply append a list of rollback items to the next response, to notify you that the status of those items is no longer valid.

In other words, if the pagination cursor that you've just sent is pointing to an item that's no longer part of the main chain, the API will do the heavy lifting by shifting the cursor back into the main chain and returning a list of rollback items whose status you might want to update.

Under the Hood

Here is a step-by-step explanation of how our data pipeline handles a pagination cursor that's pointing to a reorged block (Pc). This is purely informative and you don't need to understand it to successfully use the API, as most of this logic takes place in our backend.

The API will determine A, the most recent common ancestor of Pc and the current tip of the main chain

Create a meta.rollback collection that includes all the relevant items on the stale branch (according to the active filters)

For page[next]: create a data collection that returns all the relevant items on the main chain (according to the active filters), whose block number is less than or equal toA

For page[prev]: same as above, but the block number needs to be strictly greater thanA

Let's take a more granular example:

Assume the active query asks for all transactions of a given account X.

The transactions matching the active query are highlighted in the image as lines inside blocks. Note that some blocks might not have any transactions related to the account X, so they are shown empty (no lines) in the image.

The cursor C points to a transaction that’s outside the main chain (block Pc).

The API will send a meta.rollback collection that includes all the transactions of X in the orange blocks.

Important: The rollback dataset won't include all transactions from all the orange blocks, but only the ones that match the active filters (in this example, only the transactions associated with the account X).

Note: The rollback dataset is not paginated, it will include all the relevant items in a single list of resource identifier objects (only the type and id is provided for each rollback item).

For page[next]=C, the API will send a data collection that includes the next page[limit] transactions matching the active filters, starting with (and including) block A (note that some blocks might not have any transactions for account X, in this example A and M3 don’t have matching transactions).

The same applies for page[prev], but with blocks higher than (and not including) A.

Here is an abstracted example for the query /accounts/X/transactions?page[limit]=3&page[next]=C in the context of the diagram above:

{"data":[{"type":"Transaction","id":"M5-tx1",// ... more Transaction details},{"type":"Transaction","id":"M4-tx1",// ... more Transaction details},{"type":"Transaction","id":"M2-tx1",// ... more Transaction details}],"meta":{"rollback":[// only the resource identifiers, no other details{"type":"Transaction","id":"P6-tx1"},{"type":"Transaction","id":"P6-tx2"},{"type":"Transaction","id":"P4-tx1"},{"type":"Transaction","id":"R1-tx1"},{"type":"Transaction","id":"Pc-tx1"},{"type":"Transaction","id":"Pc-tx2"},{"type":"Transaction","id":"Pc-tx3"},{"type":"Transaction","id":"P1-tx1"},{"type":"Transaction","id":"P1-tx2"}// always includes the full list, no pagination]}}

Webhooks

Webhooks allow users to monitor any given query for updates and receive real-time notifications
when new resources that satisfy the query criteria become part of the blockchain.

Motivation

Let's take the example of monitoring inbound and outbound DAI transfers for the 0x0 account.

We can use the account and token filters on the token transfers endpoint
to retrieve a list of transfers, then periodically poll the links.prev link to retrieve fresh updates (the prev link
asks for the previous page, which consists of more recent items than the first item in the current list).

This approach is inconvenient, as it adds a certain delay (the polling interval) and creates many
requests that will result in empty responses.

With the new Webhooks system, users can register a Webhook instance that monitors a given query and sends
a HTTP POST request to a configurable target URL as soon as new resources that match the query have been
included in the chain.

Webhook Behavior

Each Webhook instance is associated with an underlying data query - expressed via the webhook's endpoint,
filters and confirmations attributes. For the example above, the underlying query is

The webhook will monitor the result set of this query and synchronize the results with the target
(remote server) by keeping track of an internal cursor and pushing paginated results in two
distinct stages:

The backfill stage: starting with the earliest (oldest) entry in the dataset, pages of
maximum 100 items will be POSTed to the target URL.

The live stage: as soon as the entire history is synchronized, the webhook will hibernate
until one (or potentially more) new items are included in the dataset as a result of a new block
being appended to the chain. The webhook will then issue a POST request to the remote URL and
send the new items in the body of the request.

The payload of each HTTP POST issued to the target URL will include a list of resources
(under the data property) and meta information about the Webhook:

Webhook Management

API users can manage their own decicated Webhooks programatically using a separate set of
endpoints detailed in the Webhooks section below.

Data Model

The follwing section provides a comprehensive list of all the API endpoints and their associated responses.

The Resource data model borrows a lot from EthOn - the community-sourced Ethereum Ontology. You can use it as a secondary reference for the response schema.

Note: You can access a detailed view of each response (including descriptions of all the fields) by expanding the green pills underneath each endpoint (e.g. the expandable green area reading '200 Block').

Blocks

A Block is the basic element of a 'blockchain'. It functions as an entry in a distributed ledger, recording a series of transactions together with a reference to the previous block. A block is chained to its preceeding block by a cryptographic hash of its contents as a means of reference. Blocks contain an identifier for the final state after all transactions contained in it are validated. There is a consensus mechanism that provides incentives for nodes adding new blocks to the chain ("miners" in the Proof of Work protocol used by the main Ethereum network) that comply with the rules of Ethereum by issuing newly generated tokens ('Ether') to an account specified by the block's author.

All blocks

Returns the list of all Block resources that are currently part of the main (canonical) chain, in reverse chronological order (most recently mined first).

Block by hash

Returns the Block resource identified by a given block hash. The block can either be part of the current main (canonical) chain or part of a stale (reorged) branch, if the branch was visible to Alethio's network nodes at the time of the reorg.

Filter by canonical status

Returns the list of Block resources filtered by their status of being included in the current canonical (main) chain produced by the consensus network. If this filter is not set explicitly set, its implicit value is true.

Accounts

An Account is the superclass of all account types in Ethereum. All accounts are identified by an address (which, however, is derived differently for external and contract accounts) and an account state that contains the contract's balance and total message count, which is called its nonce. Contract accounts also have an associated storage state and EVM code. The address of an external account is derived from the public key of a public and private keypair, while a contract account address is a concatenation of the creator account's address and its nonce.

Account transactions

Returns the list of Transaction resources associated with a given Account, sorted
in reverse chronological order (most recent first). Both the transactions originating from
and sent to the account are included.

This collection supports the same filters as the
Transactions
collection.

Account contract messages

Returns the list of ContractMessage resources associated with a given Account, sorted
in reverse chronological order (most recent first). Both the contract messages originating from
and sent to the account are included.

Account Ether transfers

Returns the list of EtherTransfer resources associated with a given Account, sorted
in reverse chronological order (most recent first). Both the transfers that were sent to or received
by the account are included.

This collection supports the same filters as the
EtherTransfers
collection.

Account token transfers

Returns the list of TokenTransfer resources associated with a given Account, sorted
in reverse chronological order (most recent first). Both the transfers that were sent to or received
by the account are included.

This collection supports the same filters as the
TokenTransfers
collection.

Contracts

A Contract account is an account whose behaviour is controlled by a smart contract. Contract accounts are identified by their address which is derived from the creator account's address and nonce. A contract account has a non-empty associated EVM code. It's state data consists of the bytecode, the contract's balance and the storage state of the contract's code (for example the value of variables). A contract account can only act when it is triggered by a message. It may not create and sign transactions, but it can receive transactions from external accounts as well as send and receive contract messages, which may involve a transfer of Ether. Contract accounts can also contain events which create log entries when triggered.

Contract messages

Returns the list of ContractMessage resources associated with a given Contract, sorted in reverse chronological order (descending by their globalRank attribute). Both the contract messages originating from and sent to the contract are included.

Transactions

A Transaction is a message between two accounts that may transfer Ether and may contain a payload. Transactions always originate from an external account that is controlled by an external actor by means of a private key. The execution of a transaction creates a 'transaction receipt'.