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