REST API

The crums.io REST API is documented on this page. Note this is not a normative description of the hashing procedures we use to construct Merkle trees and proofs. For more information on these structures see here.

URI Endpoints

The methods in this API can all be accessed via HTTP GET. Even when the HTTP call causes a change in state of the system or causes a new resource (eg crumtrail artifacts) to be created. This is not RESTy, as a GET call is supposed to be a verb that has no side effects (reads but doesn't touch); but it's convenient. There is one (optional) POST method, but that too is just for convenience. So with this in mind, think of the choice of HTTP method in this REST API as a transport layer concern: it doesn't have verb semantics.

Response

The response format is JSON. With one notable exeception, the HTTP response status is always 200 (OK); the exception is when the system witnesses a hash it doesn't remember seeing: in that case, the an HTTP 202 (Accepted) since a new record is in the process of being created. (See below).


/api/stamp
Description

Retrieves and returns an already generated crumtrail given a SHA-256 hash, if found; otherwise HTTP status 202 (Accepted) is returned: the content is a newly created crum. (Actually, this method is idempotent, so if you call this time method with the same hash seconds later, the existing crum you created seconds ago is returned.)

A crumtrail encapsulates a crum and a Merkle proof establishing a path from the hash of the crum to the root of a newly published Merkle tree.

The hash of a crum is computed from its binary representation as a sequence of bytes: 32 bytes for the hash witnessed, followed by 8 bytes for the witness time in UTC milliseconds. So the hash of a crum is the SHA-256 of this 40-byte sequence.

202 Side effect: if a crumtrail for a submitted hash cannot be found, then a new crum for that hash is automatically generated. In turn, the crum for this hash will be included in a subsequent Merkle tree. The net effect is that if this call first fails to return a crumtrail for a given hash, it will succeed on that same hash a few minutes later.

Method GET
Paramaters
hash SHA-256 hash of the object expressed as a 64 digit hexadecimal number.
Example
https://crums.io/api/stamp?hash=41f4915e20..
.
/api/verify_stamp
Description

Verifies an uploaded crumtrail (timestamp). If it's at all old, the service will have long forgotten about the uploaded crumtrail and the hash that was used to generate it. But the service does remember the root of the Merkle tree of every crumtrail it has ever generated, and that root is sufficient to validate one of its proofs. There's some flexibility in the layout of an uploaded crumtrail. If the uploaded JSON crumtrail, contains any user-defined fields, they are ignored without a fuss.

Note since the roots of our Merkle trees are pubished and publicly advertised on 3rd party properties, this API method can be classified as a convenience method: a crumtrail can be verified by the user independently.

This method supports both POST and GET.

Method POST
Body A crumtrail as downloaded via api/stamp
Method GET
Paramaters
crumtrail URL encoded crumtrail as downloaded via api/stamp.
Response
Success OK
Failure FAIL
Examples
curl -X POST -H "Content-type: text/plain" --data-binary @mypath/to/crumtrail https://crums.io/api/verify_stamp
http://crums.io/api/verify_stamp?crumtrail=%7B%22crum%22%3A%7B%22utc%22%3..
/api/list_roots
Description

Lists the roots of the Merkle trees the service has published starting from a given time in chronological or reverse chronological order.

Method GET
Paramaters
utc The start time in UTC milliseconds (inclusive).
count Specifies the maximum number of records to return as well as the direction of the enumeration (chronological, or reverse chronological). The sign of the number indicates the direction (negative is reverse), and the magnitude (absolute value) indicates the maximum number of records to return.
Response A list of records, each record containing the root hash of the Merkle tree, the minimum (first) UTC of any crum in that tree, and the maximum (last) UTC of any crum in the tree.
Example
4 roots starting from June 2030, in reverse chronological order, i.e. the 4 latest roots:
https://crums.io/api/list_roots?utc=1907770136768&count=-4
/api/root_trail
Description

Returns a path of hashes linking the previous Merkle tree to the root of the given tree. In actuality, it's just a Merkle proof of the last leaf in the tree: every Merkle tree crums.io creates has the root of the previous tree as its last leaf.

Method GET
Paramaters
hash The root of the Merkle tree. A SHA-256 hash expressed as a 64 digit hexadecimal number.
Response

On success the hash argument identifies a known Merkle tree and returns a Merkle proof of the last leaf in the tree. The last leaf in the tree is always arranged so that it contains that root hash of the last Merkle tree that this tree points to. That is, each crums.io Merkle tree contains a hash pointer to the tree it succeeds. These records in the crums.io ecosystem never expire: they are maintained indefinitely.

If the hash argument is not a known Merkle tree, then 404 Not Found is returned.

Example
https://crums.io/api/root_trail?hash=43a54f73050a . .
/api/beacon
Description

Returns the latest Merkle tree record generated by the service. Since the value at the root of the next Merkle tree cannot be predicted in advance, the value for the latet tree can be used as a coarse-grained beacon. If this value is in turn embedded in a product, depending on how embedded it is (how difficult it is to substitute this embedding with another), a product can prove its freshness via the value.

Method GET
Response A record containing the root hash of the latest Merkle tree, the minimum (first) UTC of any crum in that tree, and the maximum (last) UTC of any crum in the tree.
Example
https://crums.io/api/beacon
/api/qr_beacon
Description

Returns the latest Merkle tree record generated by the service as a QR code. If this image is embedded in a product, depending on how embedded it is (e.g. it appears somewhere on scene in a video), a product can prove its freshness via the value.

Method GET
Response A QR code containing the root hash of the latest Merkle tree, and the maximum (last) UTC of any crum in that tree.
Example
https://crums.io/api/qr_beacon

© 2020-2022 crums.io