Introduction
You can get the latest version of the Stampery API client library for your preferred language on GitHub:
- Node.js → https://github.com/stampery/node
- PHP → https://github.com/stampery/php
- Python → https://github.com/stampery/python
- Ruby → https://github.com/stampery/ruby
- Elixir → https://github.com/stampery/elixir
- Java → https://github.com/stampery/java
- Go → https://github.com/stampery/go
This is the documentation for version 3 of the Stampery API, the industrial-scale data certification platform.
With the Stampery API you can certify a virtually unlimited amount of datasets or files by embedding their unique identifiers into both the Bitcoin and Ethereum public blockchains.
For every certification and blockchain, you get a receipt document called proof that allows you to prove the timestamped existence, integrity and ownership of the certified data.
Client libraries are available for NodeJS, PHP, Python, Ruby, Elixir, Java and Go.
You can view code examples across this documentation in the dark area to the right, and switch between different programming languages with the tabs in the top right.
Authentication
stampery = new Stampery('367c6ec2-5791-4cf5-8094-4bae00c639b4');
stampery = new Stampery '367c6ec2-5791-4cf5-8094-4bae00c639b4'
<?
$stampery = include('stampery.inc.php');
$stampery = new Stampery('830fa1bf-bee7-4412-c1d3-31dddba2213d');
from stampery import Stampery
client = Stampery('2d4cdee7-38b0-4a66-da87-c1ab05b43768', 'prod')
defmodule MyStampingModule do
use Stampery, {"2d4cdee7-38b0-4a66-da87-c1ab05b43768", :prod}
def on_ready do
end
def on_proof(proof) do
end
def on_error(error) do
end
end
MyStampingModule.start()
require 'stampery'
stampery = Client.new '2d4cdee7-38b0-4a66-da87-c1ab05b43768'
import com.stampery.Stampery;
Stampery stampery = new Stampery("2d4cdee7-38b0-4a66-da87-c1ab05b43768");
stampery.subscribe(this);
stampery.start();
events := stampery.Login("2d4cdee7-38b0-4a66-da87-c1ab05b43768")
Authentication is performed by using app-specific secret tokens.
You can signup and generate your own secret tokens with the API dashboard.
Hashing
stampery.hash("Hello world!", function(hash) {
console.log(hash);
});
stampery.hash "Hello world!", (hash) ->
console.log hash
<?
$digest = $stampery->hash("Hello world!");
echo(hash);
digest = client.hash("Hello world!")
print(digest)
digest = MyStampingModule.hash("Hello world!")
IO.puts digest
digest = stampery.hash "Hello world!"
digest = stampery.hash("Hello world!");
digest := stampery.Hash("Hello world!")
For your convenience, all our client libraries provide a hash function that takes any kind of string and directly outputs a ready to stamp hash digest.
Stamping
Stamping a hash
stampery.on('proof', function(hash, proof) {
console.log('Received proof for hash ' + hash, proof);
});
stampery.hash(digest);
stampery.on 'proof', (hash, proof) ->
console.log "Received proof for hash #{hash}", proof
stampery.stamp digest
<?
$stampery->stamp($digest);
client.stamp(digest)
Stampery.stamp digest
stampery.stamp digest
stampery.stamp(digest);
stampery.Stamp(digest)
Our API is capable of stamping SHA3-512 (FIPS-202) hashes directly.
For stamping a SHA3-512 hash, you only have to make a call to the stamp
method of our API, as seen in the examples to the right.
Stamping a file
stampery.on('proof', function(hash, proof) {
console.log('Received proof for hash ' + hash, proof);
});
fs.readFile('/etc/hosts', 'utf8', function(err, data) {
stampery.hash(data, stampery.stamp);
});
stampery.on 'proof', (hash, proof) ->
console.log "Received proof for hash #{hash}", proof
fs.readFile '/etc/hosts', 'utf8', (err, data) ->
stampery.hash data, stampery.stamp
<?
$stampery.on('proof', function(hash, proof){
echo("Received proof for hash" . $hash . "\n");
var_dump($proof);
});
$file = file_get_contents('/path/to/file.txt');
$digest = $stampery->hash($file);
$stampery->stamp($digest);
def on_proof(hash, proof):
print("Received proof for " + hash)
print(proof)
file = open("/path/to/file.txt")
digest = client.hash(file.read())
client.stamp(digest)
defmodule MyStampingModule do
use Stampery, {"2d4cdee7-38b0-4a66-da87-c1ab05b43768", :prod}
def on_proof(proof) do
IO.puts("Received proof for hash #{inspect proof.hash}")
IO.inspect(proof)
end
end
{:ok, data} = File.read("/path/to/file.txt")
digest = Stampery.hash(data)
MyStampingModule.stamp(digest)
stampery.on :proof do |hash, proof|
puts 'Received proof for'
puts hash
puts 'Proof'
puts proof.to_s
end
data = File.read "/path/to/file.txt"
digest = stampery.hash data
stampery.stamp digest
// the following code should be inside a class that implements our Consumer interface
public void onProof(String hash, Proof proof) {
System.out.println(hash);
System.out.println(proof);
}
public void onReady() {
String file = "";
try{
file = new String(Files.readAllBytes(Paths.get("/path/to/file.txt")));
}catch(IOException e){
e.printStackTrace();
}
String digest = stampery.hash(file);
stampery.stamp(digest);
}
for event := range events {
switch event.Type {
case "ready":
data, err := ioutil.ReadFile("/path/to/file.txt")
if err != nil {
log.Fatalf("Error %v\n", err)
}
digest := stampery.Hash(string(data))
stampery.Stamp(digest)
case "proof":
fmt.Println("\nProof")
p := event.Data.(stampery.Proof)
fmt.Println("Hash: ", p.Hash)
fmt.Printf("Version: %v\nSiblings: %v\nRoot: %v\n", p.Version, p.Siblings, p.Root)
fmt.Printf("Anchor:\n Chain: %v\n Tx: %v\n", p.Anchor.Chain, p.Anchor.Tx)
case "error":
log.Fatalf("%v\n", event.Data)
}
}
Stamping a file is just as easy as obtaining its SHA3-512 hash and then stamping the hash as explained in the previous section.
For your convenience, all our client libraries include a function for hashing files as seen in the examples to the right.
Proofs
About proofs
Proofs are JSON documents proving that a certain file or dataset has been anchored to a certain public blockchain.
Anyone holding the original data and its corresponding proof can verify the certification by following the proving process described here.
Proof format
This is the structure of a proof:
Where v
, s
, r
, c
and t
are:
Key | Description | Value type |
---|---|---|
v | BTA version used. | Integer(1) |
s | Merkle siblings. | Array |
r | Merkle root. | String(128) |
c | Chain code. | Integer(1) |
t | Transaction ID (txid) | String(64) |
Valid chain codes for c
are:
Value | Chain |
---|---|
1 | Bitcoin livenet |
2 | Ethererum livenet |
Retrieving missed proofs
stampery.on('proof', function(hash, proof) {
console.log('Received missed proof for hash ' + hash, proof);
});
stampery.receiveMissedProofs();
stampery.on 'proof', (hash, proof) ->
console.log "Received missed proof for hash #{hash}", proof
stampery.receiveMissedProofs()
If you make a stamp and for some reason disconnect from our service right after, you will miss the proof.
Don’t worry, missed proofs are queued in our servers for 24h, and you can retrieve them by making a simple call to the receiveMissedProofs
method.
Checking a proof (proving)
stampery.prove(hash, proof, function (valid) {
console.log('Proof validity:', valid);
});
stampery.prove hash, proof, (valid) ->
console.log 'Proof validity:', valid
MyStampingModule.prove(proof)
We call proving to the process of verifying a proof is valid and therefore demonstrating that a hash or file has been undoubtfully embedded in the blockchain and it has not been tampered since then.
Proofs are independently verifiable by everyone in possesion of the hash or file and the proof itself.
The process of proving Stampery proofs made with the current version 5 of our BTA platform is made like this:
- Take the hash
- Take first element in the Merkle siblings list
s[0]
- Concatenate both, putting the biggest of them in front
- Hash the resulting string with
SHA3-512
- Take the resulting hash and the next element in the Merkle siblings list, concatenate like before and hash the resulting string
- Repeat same process until there are no elements left in the Merkle siblings list
- Check the resuting string matches the Merkle root of the proof,
r
- Take the transaction ID,
t
, and paste in your favorite Bitcoin/Ethereum chain explorer - Check that the Merkle root,
r
, matches the tail of the data embedded in the transaction
If the checks in steps 7 and 9 pass, then you have proved that the proof is OK and the hash or file has not been tampered.