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.
  • The possibility to send an email with the receipt as attachment when this receipt is complete

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.3.0 - May 30, 2018
    • There was a bug in the previous version when calling GET /timestamp shortly after POST /digest. This version fix this. Moreover the Pending attestation from the authenticated calendar is always returned in the GET /timestamp avoiding possible loss of data.
    • It's now possible to send a complete receipt to an email, if requested to the /digest method. This could help to prove to a third party to timestamp a unique history of events.
    • The hash type of the digest has been moved from the /timestamp method to the /digest
  • Version 0.2.1 - May 21, 2018
    • Documentation fixes and upgrades
  • 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 initial default is the last version at the start of the contract.
    • 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.3.0

Authentication

signature

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
type
string
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
in header
string

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.

op
in query
string

this optional parameter specify wich hash was used to create the digest, when creating a detached timestamp this hash will be specified in the header. When this is not specified it is used sha256 as default

email
in query
string

this optional parameter specify an email address. When the receipt is completed an email will be sent to this address, containing the following information: the digest, the full receipt as attachment, the hash of the public key of the customer and his signature. This is useful to inform a third party of the timestamps, proving a unique list of events.

Request Content-Types: application/octet-stream
Request Example
"c775d5cc6dab23684842dc86ffcffb34c8022f0819f6729cbd9768cabd25b5af"

The request is correctly accepted by the server which immediately return the receipt in pending 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)
"f010525a90f5a4e73c636664a3c1c8fcc5f4080083dfe30d2ef90c8e272668747470733a2f2f617574682e63616c656e6461722e657465726e69747977616c6c2e636f6d"

GET /timestamp/{digest}

Get a timestamp receipt providing the digest

digest
in path
string

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

allow-dubious
in query
string

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

detached
in query
boolean

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. The hash used in the header is the one requested during the call to /digest or the default sha256 if nothing was specified.

shrink
in query
string

if this parameter exists the data returned will contain only the oldest BitcoinBlockHeaderAttestation.

x-version
in header
string

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.

200 OK

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 PendingReceipt is returned.

400 Bad Request

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

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
in path
string

the document digest to verify.

x-version
in header
string

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.

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": 1456825200,
        "humanReadable": "Jan 03 2016 (UTC)",
        "type": "Litecoin"
      },
      {
        "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"

PendingReceipt: binary

An OpenTimestamps pending receipt in binary format (showed as hex string just for reader's convenience).
Pending means to prove the timestamps it trusts the calendar (in this case https://auth.calendar.eternitywall.com ) will provide the necessary information to link the digest to the blockchain. Once upgraded to a complete Receipt the verification is totally independent from the calendar.
The value in the example is the binary returned from the server, to create a stand-alone receipt you need to prepend a valid Header. The following is the textual reprentation of a stand-alone receipt (which is the verbose info output from the reference lib ots -v <receipt>.ots)

File sha256 hash: 45f6176754af00b1178c40559d3bbaf39c3116165645cdff201bd411e7c1123d
Timestamp:
append 525a90f5a4e73c636664a3c1c8fcc5f4
sha256
verify PendingAttestation(' https://auth.calendar.eternitywall.com')

Example
"f010525a90f5a4e73c636664a3c1c8fcc5f4080083dfe30d2ef90c8e272668747470733a2f2f617574682e63616c656e6461722e657465726e69747977616c6c2e636f6d"

Receipt: 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.
The output in this example is obtained with the detached parameter, which is the same as adding the Header to the value returned from the server without any options, so it's a stand alone receipt.

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"

Header: binary

This an example header of a .ots receipt, the first 32 bytes are the magic header specific to every .ots file, the following byte is the hash type, which in the example is 08 for sha256 followed by the bytes of the hash of the file this receipt refer to. By concatening the binary of this header with the PendingReceipt previous example you get a full .ots Receipt

Example
"004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010845f6176754af00b1178c40559d3bbaf39c3116165645cdff201bd411e7c1123d"

Attestations: application/json

This object represent a json readable object of the attestations contained in a receipt.

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

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": 1456825200,
        "humanReadable": "Jan 03 2016 (UTC)",
        "type": "Litecoin"
      },
      {
        "unixTimestamp": 1500000000,
        "humanReadable": "Jul 14 2017 (UTC)",
        "type": "Ethereum"
      }
    ]
  }
}