OpenTimestamps authenticated calendar API Reference

This is the OpenTimestamps authenticated calendar API provided by Eternity Wall.
To use this API you need to:

  • Get in touch with us and setup a contract with the SLA you need.
  • Create a bitcoin keypair, you can use your own tool or this one
  • Send us the public key.

With this process Eternity Wall cannot charge the customer for request they didn't make, because we can't forge the signatures.
The available OpenTimestamps public calendars provide the same service with the same interface but this authenticated API provide the following advantages:

  • Customizable Service Level Agreement (SLA) with the provider for the following parameters:
    • API call response time.
    • Blockchain commitment indepentent from network fee conditions.
  • This API stores every commitment data from the client, differently from the public infrasctructure. This way the client doesn't need to store the partial receipt to obtain the full receipt cause he can ask for the full receipt with the same commitment used to create the receipt (usually the hash of the data).
  • Any new anchoring mechanism on other blockchain added server side comes for free for the client without needing to upgrade their software.
  • Provide optional http callback to the client when receipts are ready, avoiding the client to do polling. The callback is made to a URL specified by the client and contains a query parameter called digest with the value of the upgraded digest and a parameter type containing the type of commitment (actual possible value are BTC and ETH). The client could then call the /timestamp endpoint for the receipt. The callback is called for a specific commitment digest whenever there are new result in the receipt, since there could be multiple calendar server and different blockchains this means the callback for the same digest could be called more than once.
  • A verify endpoint wich allows to verify provided receipts, thus permit the client to be blockchainless. This method must be used consciounsly because require trust in the service provider, which is simply not needed if the client is able to check the truth in the blockchain.
  • There are several libraries in different languages to call the calendar public servers and manage receipts but this API potentially doesn't need any specific library from the client.

Some software libraries don't validate the SSL certificate the API use which is signed by let's encrypt. In such case try the endpoint https://eternitywall-api.appspot.com/authcal/v1

Release notes

  • Version 0.2.0 - May 10, 2018
    • The uri used for the api was https://api.eternitywall.com, which is still running, however to allow better compatibility with the open-source library we moved to https://auth.calendar.eternitywall.com which is compatible with the official whitelisted servers. This allows to upgrade receipts with the public libraries without any additional parameter.
    • To avoid breaking compatibility with customers, this and any future upgrade will go through the version system. Any update of the API will keep customers on the previous version, the customers could test the changes by passing the version as header parameter, and then ask the provider which is the desired default
    • The /timestamp endpoint now accept the detached parameter, allowing full receipt donwload.
API Endpoint
https://auth.calendar.eternitywall.com/
Contact: api@eternitywall.com
Schemes: https
Version: 0.2.0

Authentication

signature

description

The used signature is the bitcoin message signature using ECDSA with the curve secp256k1. What is being signed is specified in the relative method description. Both the Java and the Javascript implementation of OpenTimestamps perform this authentication through signature here and here.

name
x-signature
in
header

Paths

POST /digest

Post a document {digest}, usually a hash of a document, to timestamp on public blockchain. This method must be authenticated by providing a signature in the header, the message to use is the digest encoded as a hex string. (Note that examples show hex encoded string but the api use binary values)

The {digest} to timestamp in binary, examples show hex string for comprehension but the API consumes and produce data in not encoded binary ( application/octet-stream).

x-version

This parameter specify the version of the API, overriding the default value. This is useful for customer to test the compatibility of a new version before asking the provider to upgrade the default behaviour.

type
object
in
header
Request Content-Types: application/octet-stream
Request Example
"c775d5cc6dab23684842dc86ffcffb34c8022f0819f6729cbd9768cabd25b5af"

The request is correctly accepted by the server which immediately return the receipt in incomplete state (no writes on the blockchain yet). By later calling the /timestamp method the caller get all the timestamp information of this {digest}.

400 Bad Request

Bad input parameters, for example no content in the body of the request.

401 Unauthorized

The computed signature does not match. Verify with the vendor that your public key is enabled (To create your eckey pair you can use this tool). Verify that your signing the correct message (the hex string representing the submitted digest). Verify you are using the correct signing algorithm (bitcoin signing text messages)

Response Content-Types: application/octet-stream
Response Example (200 OK)
"004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010805c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9f010e754bf93806a7ebaa680ef7bd0114bf408f010b573e8850cfd9e63d1f043fbb6fc250e08f10457cfa5c4f0086fb1ac8d4e4eb0e70083dfe30d2ef90c8e2e2d68747470733a2f2f616c6963652e6274632e63616c656e6461722e6f70656e74696d657374616d70732e6f7267"

GET /timestamp/{digest}

Get a timestamp receipt providing the digest

digest

Retrieve the OpenTimestamps receipt of the document identified by digest previosly timestamped.

type
string
in
path
allow-dubious

if this parameter exists the receipt will contain also commit on blockchain considered dubious from timestamp perspective by the OpenTimestamps developer (eg. Ethereum)

type
object
in
query
detached

if this parameter exists the data returned will be a complete .ots, thus containing the header and supposing the digest is the element the receipt refer to supposing sha256 as the hash function used to create the hash. This value could also be sha1, ripemd160, keccak256 if the digest of document was created with one of this hash function.

type
object
in
query

The request is correctly accepted by the server which return a complete receipt if the timestamp transaction is correctly inserted in the bitcoin blockchain and 6 confirmation is passed (to avoid possible reorgs). If the receipt is still pending the IncompleteReceipt is returned.

400 Bad Request

Bad input parameters. Verify the {digest} is correctly encoded as hex string.

401 Unauthorized

The computed signature does not match. Verify with the vendor that your public key is enabled (To create your eckey pair you can use this tool). Verify that your signing the correct message (the hex string representing the submitted digest). Verify you are using the correct signing algorithm (bitcoin signing text messages).

Response Content-Types: application/octet-stream
Response Example (200 OK)
"004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010805c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9f010e754bf93806a7ebaa680ef7bd0114bf408f010b573e8850cfd9e63d1f043fbb6fc250e08f10457cfa5c4f0086fb1ac8d4e4eb0e7ff0083dfe30d2ef90c8e2e2d68747470733a2f2f616c6963652e6274632e63616c656e6461722e6f70656e74696d657374616d70732e6f726708f1206563bb432a829ac8d6c54d1a9330d2240664cad8338dd05e63eec12a18a68d5008f020ba83ddbe2bd6772b4584b46eaed23606b712dd740a89e99e927571f77f64aa2108f120193c81e70e4472b52811fe7837ce1293b1d3542b244f27f44182af8287fc9f4e08f120c6c57696fcd39b4d992477889d04e6882829f5fe556304a281dce258b78a1f0708f1ae010100000001b592ca038eaa9c1b698a049b09be8ee8972b5d0eca29c19946027ba9248acb03000000004847304402200f992d5dbec6edb143f76c14e4538e0a50d66bae27c683cf4291e475287ec6af022010bae9443390aadbd2e2b8b9f757beea26d3f5c345f7e6b4d81b3d390edd381801fdffffff022eb142000000000023210338b2490eaa949538423737cd83449835d1061dca88f4ffaca7181bcac67d2095ac0000000000000000226a20f004678a06000808f120977ac39d89bb8b879d4a2c38fca48a040c82637936707fc452c9db1390b515c80808f02074268b23e614997d18c7c063d8d82d7e1db57b5fc4346cc47ac2c46d54168d710808f120560c45b854f8507c8bfacf2662fef269c208a7e5df5c3145cbce417ecacc595e0808f1200dba8721b9cd4ac7c2fcc7e15ba2cb9f2906bfc577c212747cd352d61b5d7fdb0808f12081107a010d527d18baa874bc99c19a3a7a25dfe110a4c8985bf30f6c3e77baed0808f020ca3cdcd7093498b3f180b38a9773207e52fca992c2db1d660fdfa1b329500c390808f020ca6c6464dd02ced64c9c82246ccfc626caa78d9e624cc11013e3b4bbc09e98910808f0201c7ae0feac018fa19bd8459a4ae971b3e6c816a87254317e0a9f0ec9425ba7610808f12090263a73e415a975dc07706772dbb6200ef0d0a23006218e65d4a5d8112067300808f12079530163b0d912249438628bd791ac9402fa707eb314c6237b0ef90271625c840808000588960d73d7190103e8941a"

POST /verify/{digest}

Verify a timestamp receipt providing the digest. This API method is provided for convenience but by asking our API you are trusting the answer from the server while you could verify by yourself if you have a blockchain.

The ots binary receipt to verify.

digest

the document digest to verify.

type
string
in
path
Request Content-Types: application/octet-stream
Request Example
"004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010805c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9f010e754bf93806a7ebaa680ef7bd0114bf408f010b573e8850cfd9e63d1f043fbb6fc250e08f10457cfa5c4f0086fb1ac8d4e4eb0e7ff0083dfe30d2ef90c8e2e2d68747470733a2f2f616c6963652e6274632e63616c656e6461722e6f70656e74696d657374616d70732e6f726708f1206563bb432a829ac8d6c54d1a9330d2240664cad8338dd05e63eec12a18a68d5008f020ba83ddbe2bd6772b4584b46eaed23606b712dd740a89e99e927571f77f64aa2108f120193c81e70e4472b52811fe7837ce1293b1d3542b244f27f44182af8287fc9f4e08f120c6c57696fcd39b4d992477889d04e6882829f5fe556304a281dce258b78a1f0708f1ae010100000001b592ca038eaa9c1b698a049b09be8ee8972b5d0eca29c19946027ba9248acb03000000004847304402200f992d5dbec6edb143f76c14e4538e0a50d66bae27c683cf4291e475287ec6af022010bae9443390aadbd2e2b8b9f757beea26d3f5c345f7e6b4d81b3d390edd381801fdffffff022eb142000000000023210338b2490eaa949538423737cd83449835d1061dca88f4ffaca7181bcac67d2095ac0000000000000000226a20f004678a06000808f120977ac39d89bb8b879d4a2c38fca48a040c82637936707fc452c9db1390b515c80808f02074268b23e614997d18c7c063d8d82d7e1db57b5fc4346cc47ac2c46d54168d710808f120560c45b854f8507c8bfacf2662fef269c208a7e5df5c3145cbce417ecacc595e0808f1200dba8721b9cd4ac7c2fcc7e15ba2cb9f2906bfc577c212747cd352d61b5d7fdb0808f12081107a010d527d18baa874bc99c19a3a7a25dfe110a4c8985bf30f6c3e77baed0808f020ca3cdcd7093498b3f180b38a9773207e52fca992c2db1d660fdfa1b329500c390808f020ca6c6464dd02ced64c9c82246ccfc626caa78d9e624cc11013e3b4bbc09e98910808f0201c7ae0feac018fa19bd8459a4ae971b3e6c816a87254317e0a9f0ec9425ba7610808f12090263a73e415a975dc07706772dbb6200ef0d0a23006218e65d4a5d8112067300808f12079530163b0d912249438628bd791ac9402fa707eb314c6237b0ef90271625c840808000588960d73d7190103e8941a"
200 OK

The request is correctly accepted by the server which return a timestamp if the digest has been committed in the blockchain.

Response Content-Types: application/json
Response Example (200 OK)
{
  "status": "ok",
  "message": "Everything is ok!",
  "code": 0,
  "value": {
    "attestations": [
      {
        "unixTimestamp": 1432825200,
        "humanReadable": "May 28 2015 (UTC)",
        "type": "Bitcoin"
      },
      {
        "unixTimestamp": 1500000000,
        "humanReadable": "Jul 14 2017 (UTC)",
        "type": "Ethereum"
      }
    ]
  }
}

Schema Definitions

Digest: binary

A digest in binary, usually some sort of hash of a document.
Examples represent this value as an hex string but the API consumes and produce binary data"

Example
"c775d5cc6dab23684842dc86ffcffb34c8022f0819f6729cbd9768cabd25b5af"

Attestations: application/json

description

Example
{
  "attestations": [
    {
      "unixTimestamp": 1432825200,
      "humanReadable": "May 28 2015 (UTC)",
      "type": "Bitcoin"
    },
    {
      "unixTimestamp": 1500000000,
      "humanReadable": "Jul 14 2017 (UTC)",
      "type": "Ethereum"
    }
  ]
}

IncompleteReceipt: binary

An OpenTimestamps incomplete receipt in binary format.
Incomplete means to prove the timestamps it trusts the calendar (in this case https://alice.btc.calendar.opentimestamps.org ) will provide the necessary information to link the digest to the blockchain. Once upgraded to a CompleteReceipt the verification is totally independent from the calendar.
The example is the hex representation of the binary of a receipt, the following is the textual representation (which is the verbose info output from the reference lib ots -v info examples/incomplete.txt.ots)

File sha256 hash: 05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9
Timestamp:
append e754bf93806a7ebaa680ef7bd0114bf4 == 05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9e754bf93806a7ebaa680ef7bd0114bf4
sha256 == cd567f5aa9f68cfbece1ca17b4b72ad3079a3e4bff80efe131419bd02138e425
append b573e8850cfd9e63d1f043fbb6fc250e == cd567f5aa9f68cfbece1ca17b4b72ad3079a3e4bff80efe131419bd02138e425b573e8850cfd9e63d1f043fbb6fc250e
sha256 == 6716df9bd9e83595bce439c58108d8fcc1678f30d4c6731c3f1fa6c79ed712c6
prepend 57cfa5c4 == 57cfa5c46716df9bd9e83595bce439c58108d8fcc1678f30d4c6731c3f1fa6c79ed712c6
append 6fb1ac8d4e4eb0e7 == 57cfa5c46716df9bd9e83595bce439c58108d8fcc1678f30d4c6731c3f1fa6c79ed712c66fb1ac8d4e4eb0e7
verify PendingAttestation(' https://alice.btc.calendar.opentimestamps.org')

Example
"004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010805c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9f010e754bf93806a7ebaa680ef7bd0114bf408f010b573e8850cfd9e63d1f043fbb6fc250e08f10457cfa5c4f0086fb1ac8d4e4eb0e70083dfe30d2ef90c8e2e2d68747470733a2f2f616c6963652e6274632e63616c656e6461722e6f70656e74696d657374616d70732e6f7267"

Result: object

status: string ok, ko
message: string

a human readable message

code: integer (int32)

a number representing the status, if 0 is ok otherwise it depends on the method

value: Attestations
Example
{
  "status": "ok",
  "message": "Everything is ok!",
  "code": 0,
  "value": {
    "attestations": [
      {
        "unixTimestamp": 1432825200,
        "humanReadable": "May 28 2015 (UTC)",
        "type": "Bitcoin"
      },
      {
        "unixTimestamp": 1500000000,
        "humanReadable": "Jul 14 2017 (UTC)",
        "type": "Ethereum"
      }
    ]
  }
}

CompleteReceipt: binary

An OpenTimestamps receipt in binary format (showed as hex string just for reader's convenience). This receipt contains all the information to prove the digest 05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9 commit to the bitcoin blockchain. The output is not in verbose mode as the previous so it doesn't show intermediate result

File sha256 hash: 05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9
Timestamp:
append e754bf93806a7ebaa680ef7bd0114bf4
sha256
append b573e8850cfd9e63d1f043fbb6fc250e
sha256
prepend 57cfa5c4
append 6fb1ac8d4e4eb0e7
verify PendingAttestation(' https://alice.btc.calendar.opentimestamps.org')
sha256
prepend 6563bb432a829ac8d6c54d1a9330d2240664cad8338dd05e63eec12a18a68d50
sha256
append ba83ddbe2bd6772b4584b46eaed23606b712dd740a89e99e927571f77f64aa21
sha256
prepend 193c81e70e4472b52811fe7837ce1293b1d3542b244f27f44182af8287fc9f4e
sha256
prepend c6c57696fcd39b4d992477889d04e6882829f5fe556304a281dce258b78a1f07
sha256
prepend 0100000001b592ca038eaa9c1b698a049b09be8ee8972b5d0eca29c19946027ba9248acb03000000004847304402200f992d5dbec6edb143f76c14e4538e0a50d66bae27c683cf4291e475287ec6af022010bae9443390aadbd2e2b8b9f757beea26d3f5c345f7e6b4d81b3d390edd381801fdffffff022eb142000000000023210338b2490eaa949538423737cd83449835d1061dca88f4ffaca7181bcac67d2095ac0000000000000000226a20
append 678a0600
# Bitcoin transaction id 78a6be65c8ad4136f4575e94506648490a56a4b3b1fd4618854cc0e80248606c
sha256
sha256
prepend 977ac39d89bb8b879d4a2c38fca48a040c82637936707fc452c9db1390b515c8
sha256
sha256
append 74268b23e614997d18c7c063d8d82d7e1db57b5fc4346cc47ac2c46d54168d71
sha256
sha256
prepend 560c45b854f8507c8bfacf2662fef269c208a7e5df5c3145cbce417ecacc595e
sha256
sha256
prepend 0dba8721b9cd4ac7c2fcc7e15ba2cb9f2906bfc577c212747cd352d61b5d7fdb
sha256
sha256
prepend 81107a010d527d18baa874bc99c19a3a7a25dfe110a4c8985bf30f6c3e77baed
sha256
sha256
append ca3cdcd7093498b3f180b38a9773207e52fca992c2db1d660fdfa1b329500c39
sha256
sha256
append ca6c6464dd02ced64c9c82246ccfc626caa78d9e624cc11013e3b4bbc09e9891
sha256
sha256
append 1c7ae0feac018fa19bd8459a4ae971b3e6c816a87254317e0a9f0ec9425ba761
sha256
sha256
prepend 90263a73e415a975dc07706772dbb6200ef0d0a23006218e65d4a5d811206730
sha256
sha256
prepend 79530163b0d912249438628bd791ac9402fa707eb314c6237b0ef90271625c84
sha256
sha256
verify BitcoinBlockHeaderAttestation(428648)
# Bitcoin block merkle root 078cdde9c89f2e3c58c96b1658627fd9298c63c6618954ea24ac3b5a13fe18da

Example
"004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010805c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9f010e754bf93806a7ebaa680ef7bd0114bf408f010b573e8850cfd9e63d1f043fbb6fc250e08f10457cfa5c4f0086fb1ac8d4e4eb0e7ff0083dfe30d2ef90c8e2e2d68747470733a2f2f616c6963652e6274632e63616c656e6461722e6f70656e74696d657374616d70732e6f726708f1206563bb432a829ac8d6c54d1a9330d2240664cad8338dd05e63eec12a18a68d5008f020ba83ddbe2bd6772b4584b46eaed23606b712dd740a89e99e927571f77f64aa2108f120193c81e70e4472b52811fe7837ce1293b1d3542b244f27f44182af8287fc9f4e08f120c6c57696fcd39b4d992477889d04e6882829f5fe556304a281dce258b78a1f0708f1ae010100000001b592ca038eaa9c1b698a049b09be8ee8972b5d0eca29c19946027ba9248acb03000000004847304402200f992d5dbec6edb143f76c14e4538e0a50d66bae27c683cf4291e475287ec6af022010bae9443390aadbd2e2b8b9f757beea26d3f5c345f7e6b4d81b3d390edd381801fdffffff022eb142000000000023210338b2490eaa949538423737cd83449835d1061dca88f4ffaca7181bcac67d2095ac0000000000000000226a20f004678a06000808f120977ac39d89bb8b879d4a2c38fca48a040c82637936707fc452c9db1390b515c80808f02074268b23e614997d18c7c063d8d82d7e1db57b5fc4346cc47ac2c46d54168d710808f120560c45b854f8507c8bfacf2662fef269c208a7e5df5c3145cbce417ecacc595e0808f1200dba8721b9cd4ac7c2fcc7e15ba2cb9f2906bfc577c212747cd352d61b5d7fdb0808f12081107a010d527d18baa874bc99c19a3a7a25dfe110a4c8985bf30f6c3e77baed0808f020ca3cdcd7093498b3f180b38a9773207e52fca992c2db1d660fdfa1b329500c390808f020ca6c6464dd02ced64c9c82246ccfc626caa78d9e624cc11013e3b4bbc09e98910808f0201c7ae0feac018fa19bd8459a4ae971b3e6c816a87254317e0a9f0ec9425ba7610808f12090263a73e415a975dc07706772dbb6200ef0d0a23006218e65d4a5d8112067300808f12079530163b0d912249438628bd791ac9402fa707eb314c6237b0ef90271625c840808000588960d73d7190103e8941a"