The ODNS API is a series of rest services that allow easier access to the OYB Document Notarization Service (ODNS) for the Polygon Blockchain wrapping the smart contract functions and exposing it through a simple rest web service.
ODNS smart contract services can be accessed at any time by executing its smart contract methods on a Polygon Blockchain node, but ODNS API is a preferable way to start using the service without the need to deep dive into blockchain programming.
The following article provides the documentation of the API service and how to interact with the smart contract by using the ODNS API.
OYB Document Notarization Service
The main functionality of ODNS is to notarise any kind of file, document, or digital content by storing its unique hash or file signature in a distributed and decentralized ledger.
The notarization process is implemented in a specific smart contract that ensures consistent and strict rules application during the publishing process so that integrity, authenticity, ownership, and time of creation of a file can be always recovered and presented as a prove.
ODNS does not work with the documents directly, but each file is represented by its SHA-256 signature, this will ensure the great privacy possible on your documents (the document never leaves your company and cannot be stolen).
The ODNS smart contract allows you to send the following transactions:
- announce
- supersede
- retract
The announce transaction is used to publish a new document on the blockchain ledger. By announcing a document a client makes a public statement that a specific file represented by its SHA-256 signature/hash exists in its hands at the time of announcement.
The supersede transaction can be used to make a public statement that a specific new document version is available. By superseding a document a client makes a public statement that a new document represented by its SHA-256 signature replaces a specific old document.
The retract transaction can be used to make a public statement that a specific document represented by its SHA-256 signature should be considered retracted or no longer valid.
Each ODNS document is owned by an entity and generally the owner of a document is the wallet address who signed the announce transaction. A user can only supersede or retract its own document.
Any ODNS user can delegate other users to send any of the announce, supersede and retract transactions for himself. A delegated user will sign the transactions with its own private key but it can announce, supersede or retract documents as it was done by the delegee.
The document status may be checked by calling the comment method on the smart contract. The comment method returns the current status (owner, announcer, next, meta data) of a specified document represented by its SHA-256 signature.
When a document is announced, superseded, or retracted some specific events are logged to the blockchain event logs by the ODNS smart contract. By tracing these events you will be able to rebuild the history of a document as for example when it was first announced, superseded, or retracted. You will be also able to subscribe to those events and trigger some actions when those happen.
Because tracing log events does not require any interaction with the smart contract you will be always able to reconstruct your document notarization history even if for some reason in the future the contract development is halted (or the contract is destructed).
OYB document
Each ODNS document comes associated to the following status information:
- owner (wallet address of the document owner – delegee)
- announcer (wallet address of the document announcer – delegated)
- next (SHA 256 of the document that superseded the current document)
- meta data (any 32 bytes string or data associated with the document)
The owner of a document is the wallet address of the entity that owns the document, by default this address is the wallet address that signed the announce transaction.
The announcer is always the wallet address that signed the transaction (1).
In most cases, the owner address is the same address as the announcer. This is not always true: announce or supersede transactions can be sent also by a delegated user, in this case, the owner address of the document is the delegee, and the announcer address is the address of the delegated user that signed the transaction.
The next attribute of a document is the one that indicates if a document was superseded or retracted:
- if next value is 0x0000000000000000000000000000000000000000000000000000000000000000 the document was not superseded or retracted and should be considered valid.
- If next is different from 0x0000000000000000000000000000000000000000000000000000000000000000 the document was superseded or retracted and should not be considered as valid.
When next is not zero, it contains the SHA-256 signature of the document that superseded the current document. The next value of a document is used also to mark a document as retracted, in this case next value is exactly the 0x000000000000000000000000000000000000000000000000000000000000dead value.
The meta attribute is a 32 bytes string or binary data defined by the user and associated with the document (2).
Any document has its own history that starts with the announce transaction, it can be superseded zero o more times, and it ends when the last document is retracted. The first document of the list is called the origin document. Superseded documents inherit some of the attributes from the origin document, those attributes are the document owner, the meta data, and the hash of the origin document.
___________________________________
- In the current version, delegation is still in the development stage, so the owner and announcer are always the same address.
We included this announcer field in the current version because we freeze the document structure, by doing this we should be able to not change the smart contract address when this new feature is released. - Because delegation is not yet released ODNS API server, all operations on documents can only use the internal ODNS API wallet. This means that any document announced by the ODNS API will be owned by the same internal OYB wallet address. To avoid that one user can supersede or retract documents of other users the API uses the meta data attribute of the document to store a unique id related to the identity of the user of the API service. When supersede or retract methods are called this meta data status variable is checked and in case the user identity is different from the original user that created the document the method fails. Until delegation is not released the meta data variable of a document is not currently settable by the user.
Authentication
Access to OYB API requires an API Token. The token is connected to an account on OYB API website.
You can request a test account by sending an email to [email protected] [click here].
If you already have an account, you can get your API Token after logging in to this page.
You can obtain your API token also by making an HTTP GET request (using simple authentication) at URL:
https://apiproxy.ownyourbusiness.tech/dapp/api/get-auth-token/
You can do this by using the following curl command:
curl --user {someuser}:{password} \
--request GET 'https://apiproxy.ownyourbusiness.tech/dapp/api/get-auth-token/'
The API service will reply with the following JSON that included the API token and some account details:
{
"token":"01234567890abcdef01234567890abcdef",
"user_id":2,
"email":"your@email"
}
The obtained API token must be added to the request headers of API methods you are calling:
Authorization: Token 01234567890abcdef01234567890abcdef
A test account allows you to operate only on the Polygon Testnet.
Announce a document
Execute an HTTP POST on the following URL:
https://apiproxy.ownyourbusiness.tech/dapp/api/document/{document_sha_256}
CURL Example:
curl -X POST 'http://127.0.0.1:8000/dapp/api/document/0x4a0874a12ce005e142911f34c3e2db680516cafea874d3eda26b8deb0c7bb20e' \
-H 'Authorization: Token 01234567890abcdef01234567890abcdef'
Response:
{
"account": {
"credits": 37,
"dcid": "oybid:@test_comp.it"
},
"document": {
"announcer": "0x97aCA75e52D5283180a90037439fC5D6b5E7e6F2",
"hash": "0x4a0874a12ce005e142911f34c3e2db680516cafea874d3eda26b8deb0c7bb20e",
"meta": "0x6f796269643a746573745f636f6d701111111111111111111111111111111111",
"next": "0x0000000000000000000000000000000000000000000000000000000000000000",
"owner": "0x97aCA75e52D5283180a90037439fC5D6b5E7e6F2"
},
"transaction": {
"blockNumber": 22950624,
"hash": "0x494aa5d46f606f123363311ae3df14bd7fd39bf88ad937a18dcc24b57672205c",
"timestamp": 1640110109,
"type": "announce"
},
"contractAddress": "0x8cD56Bf723C8a311B51bAD6B913141B1f1d5Dc22",
"network": "polygon-mumbai"
}
The response contains three sections plus the contract address and the network.
Account section contains info related to the API user account:
Field name | Description | Note |
account.credits | number of API credits associated with the API account | this field will be removed once the smart contract will be updated to use OYB token |
account.dcid | a key assigned to each API client user account, it marks all documents notarized | this field will be removed once delegation will be implemented on the smart contract |
Document section reflects the document data and status updated to the time the transaction is done:
Field name | Description | Note |
document.owner | OYB API wallet address | once delegation will be implemented on smart contract this address will become the document owner address |
document.announcer | OYB API wallet address | once delegation will be implemented on smart contract this address will become the delegated user wallet address |
document.hash | Document SHA-256 signature | |
document.meta | A string representing the owner (dcid) of the document | in a future version of API/smart contract this field will be free to use by the client. It may be used to specify any document-related meta data as a serial number, the file name, etc |
document.next | Always 0x0..0 |
Transaction section contains info related to the mined transaction:
Field name | Description | Note |
transaction.blockNumber | Block number the transaction was mined | |
transaction.hash | Transaction hash the document was announced/superseded/retracted | |
transaction.timestamp | Timestamp of the relative block number the transaction was mined | |
transaction.type | Any of the transaction type (announce, supersede, retract) |
Supersede a document
Execute an HTTP POST on the following URL:
https://apiproxy.ownyourbusiness.tech/dapp/api/document/{new_document_sha_256}
The document to supersede is specified in the data field on the request by including a json with following format:
{"replaces": "old_documet_sha_256"}
CURL Example:
curl -X POST -H 'Content-Type: application/json' -d '{"replaces": "0x4a0874a12ce005e142911f34c3e2db680516cafea874d3eda26b8deb0c7bb20e"}' \
'http://apiproxy.ownyourbusiness.tech/dapp/api/document/0xa17a436a13784705cb6e2f870ef545d64fdbdd1e43be9ede1193284691ad8211' \
-H 'Authorization: Token 01234567890abcdef01234567890abcdef'
The response to supersede message is similar to the announce response except it returns also the superseded document data as oldDocument, the data of the new superseding document in document and transaction.type is the string “supersede”:
{
"account": {
"credits": 36,
"dcid": "oybid:test_comp"
},
"document": {
"announcer": "0x97aCA75e52D5283180a90037439fC5D6b5E7e6F2",
"hash": "0xa17a436a13784705cb6e2f870ef545d64fdbdd1e43be9ede1193284691ad8211",
"meta": "0x6f796269643a746573745f636f6d701111111111111111111111111111111111",
"next": "0x0000000000000000000000000000000000000000000000000000000000000000",
"owner": "0x97aCA75e52D5283180a90037439fC5D6b5E7e6F2"
},
"oldDocument": {
"announcer": "0x97aCA75e52D5283180a90037439fC5D6b5E7e6F2",
"hash": "0x4a0874a12ce005e142911f34c3e2db680516cafea874d3eda26b8deb0c7bb20e",
"meta": "0x6f796269643a746573745f636f6d701111111111111111111111111111111111",
"next": "0xa17a436a13784705cb6e2f870ef545d64fdbdd1e43be9ede1193284691ad8211",
"owner": "0x97aCA75e52D5283180a90037439fC5D6b5E7e6F2"
},
"transaction": {
"blockNumber": 22952064,
"hash": "0xa6b156a5d798e6138e3b067df21bed1ee318bb19dcf3cf7fc374189999a9c9c9",
"timestamp": 1640113396,
"type": "supersede"
},
"network": "polygon-mumbai",
"contractAddress": "0x8cD56Bf723C8a311B51bAD6B913141B1f1d5Dc22"
}
The field oldDocument contains the old document data. You can notice how the old document state changes, infact oldDocument.next now contains the SHA 256 signature of the new document.
Retract a document
Execute an HTTP DELETE on the following URL:
https://apiproxy.ownyourbusiness.tech/dapp/api/document/{document_sha_256}
CURL Example:
curl -X DELETE 'http://apiproxy.ownyourbusiness.tech/dapp/api/document/0xa17a436a13784705cb6e2f870ef545d64fdbdd1e43be9ede1193284691ad8211' \
-H 'Authorization: Token 01234567890abcdef01234567890abcdef'
The response to retract message is similar to the announce response except for document.next that is set to 0xdead value and transaction.type is the string “retract”.
{
"transaction": {
"type": "retract",
"timestamp": 1639407546,
"hash": "0xb9071fc2a58cfca93f3d8fe9d847849f9f84b7254d0e54d60febc96bffa41f29",
"blockNumber": 22613732
},
"document": {
"hash": "0xdacacdea7188cf128887c926de45696387094969e9c9c81e674f37f1a49be546",
"owner": "0xEb729A5bB788C87888fD23e4b247b1A0EFc06d2B",
"announcer": "0xEb729A5bB788C87888fD23e4b247b1A0EFc06d2B",
"meta": "0x6f796269643a406f79622e746563681111111111111111111111111111111111",
"next": "0x000000000000000000000000000000000000000000000000000000000000dead"
},
"contractAddress": "0xA7d9cE4C7Aff81022F639045f4d47241334cdabc",
"network": "polygon-mumbai"
}
Check to announce message documentation for more details.
Check document status
The document status can be obtained by sending the message comment to the smart contract. The comment method only checks for the document status and does not return information related to the transaction it was created. The comment method is free and does not require authentication.
You can request for comment on a document by executing an HTTP GET at the URL:
https://apiproxy.ownyourbusiness.tech/dapp/api/document/{document_sha_256}
CURL Example:
curl -X GET 'http://127.0.0.1:8000/dapp/api/document/0xa17a436a13784705cb6e2f870ef545d64fdbdd1e43be9ede1193284691ad8211' \
-H 'Authorization: Token 01234567890abcdef01234567890abcdef'
The response to comment message is similar to the announce response except that the transaction data is not returned. Transaction data are not stored in the document because the transaction data are available after method execution when the transaction is mined.
{
"document": {
"announcer": "0x97aCA75e52D5283180a90037439fC5D6b5E7e6F2",
"hash": "0xa17a436a13784705cb6e2f870ef545d64fdbdd1e43be9ede1193284691ad8211",
"meta": "0x6f796269643a746573745f636f6d701111111111111111111111111111111111",
"next": "0x000000000000000000000000000000000000000000000000000000000000dead",
"owner": "0x97aCA75e52D5283180a90037439fC5D6b5E7e6F2"
},
"network": "polygon-mumbai",
"contractAddress": "0x8cD56Bf723C8a311B51bAD6B913141B1f1d5Dc22"
}
Trace a document
Applications often use event logs to capture and describe what’s going on at a specific moment on a smart contract. These logs are often used to detect specific events or notify the viewer of the logs that something happened.
ODNS smart contract defines the following events and some constants that are used when events are emitted.
event Documented(bytes32 indexed hash, bytes2 operation, bytes32 indexed replaceHash);
event Transacted(address indexed _address, bytes32 hash);
bytes32 constant ZERO = 0x0000000000000000000000000000000000000000000000000000000000000000;
bytes32 constant RETRACTED = 0x000000000000000000000000000000000000000000000000000000000000dead;
bytes2 constant OP_ANNOUNCE = 0x0001;
bytes2 constant OP_SUPERSEDE = 0x0002;
bytes2 constant OP_RETRACT = 0x0003;
By tracing all documented events you will be able to reconstruct the history of each document in the ODNS system. The documented event can be searched by the origin document hash and the resulting events will provide all operations on the document (announced, superseded, or retracted) and the relative block number/timestamp it was mined.
The transacted event traces transactions made by a wallet address. By tracing the transacted events you will be able to get a list of transactions made by the document owner address or by the announcer/delegated user address.
The announce transaction emits these events:
emit Documented(new_document_hash, OP_ANNOUNCE, ZERO);
emit Transacted(delegated_address, new_document_hash);
emit Transacted(owner_address, new_document_hash);
The supersede transaction emits these events:
emit Documented(superseding_document_hash, OP_ANNOUNCE, ZERO);
emit Documented(origin_document_hash, OP_SUPERSEDE, superseding_document_hash);
emit Transacted(delegated_address, new_document_hash);
emit Transacted(owner_address, new_document_hash);
Please notice that in the supersede transaction two documented events are emitted, one with the new document hash and one with the origin document hash. This will allow searching events of a superseded document by the origin document hash or by the superseding document hash.
The retract operation emit these events:
emit Documented(origin_document_hash, OP_RETRACT, last_document_hash);
emit Documented(last_document_hash, OP_RETRACT, origin_document_hash);
emit Transacted(delegated_address, origin_document_hash);
emit Transacted(owner_address, origin_document_hash);
Please notice that also in the retract transaction two documented events are emitted, one with the origin document hash and one with the retracted document hash. This will allow searching of events of a retracted document by the origin document hash or by the retracted document hash.
ODNS API provides a simple implementation for scanning events by the origin document hash. To call the trace method you can make an HTTP get to the following URL;
https://apiproxy.ownyourbusiness.tech/dapp/api/trace/{document_sha_256}
CURL Example:
curl -X GET 'hppt://apiproxy.ownyourbusiness.tech/dapp/api/document/0x47224a3068288d010f31d23a0fc22ae2b35021e62576d26380137a3e4f49ef7d' \
-H 'Authorization: Token 01234567890abcdef01234567890abcdef'
The response to trace is a JSON containing a list of events:
{
"events": [{
"type": "announce",
"blockNumber": 22613508,
"blockTimestamp": 1639407086,
"transactionHash": "0xf1937435e707b94c7cb65eaef1e60fe1ab4193434325d06511f7552754a6ea3f",
"eventHash1": "0x47224a3068288d010f31d23a0fc22ae2b35021e62576d26380137a3e4f49ef7d",
"eventHash2": "0x0000000000000000000000000000000000000000000000000000000000000000",
"document": {
"hash": "0x47224a3068288d010f31d23a0fc22ae2b35021e62576d26380137a3e4f49ef7d",
"owner": "0xEb729A5bB788C87888fD23e4b247b1A0EFc06d2B",
"annoucer": "0xEb729A5bB788C87888fD23e4b247b1A0EFc06d2B",
"meta": "0x6f796269643a406f79622e746563681111111111111111111111111111111111",
"next": "0xdacacdea7188cf128887c926de45696387094969e9c9c81e674f37f1a49be546"
}
}, {
"type": "supersede",
"blockNumber": 22613635,
"blockTimestamp": 1639407348,
"transactionHash": "0x307e806015d096630f7bb197faaca13b11dd6d4f134ec886ca3b5c47ca90d66a",
"eventHash1": "0x47224a3068288d010f31d23a0fc22ae2b35021e62576d26380137a3e4f49ef7d",
"eventHash2": "0xdacacdea7188cf128887c926de45696387094969e9c9c81e674f37f1a49be546",
"document": {
"hash": "0xdacacdea7188cf128887c926de45696387094969e9c9c81e674f37f1a49be546",
"owner": "0xEb729A5bB788C87888fD23e4b247b1A0EFc06d2B",
"annoucer": "0xEb729A5bB788C87888fD23e4b247b1A0EFc06d2B",
"meta": "0x6f796269643a406f79622e746563681111111111111111111111111111111111",
"next": "0x000000000000000000000000000000000000000000000000000000000000dead"
}
}, {
"type": "retract",
"blockNumber": 22613732,
"blockTimestamp": 1639407546,
"transactionHash": "0xb9071fc2a58cfca93f3d8fe9d847849f9f84b7254d0e54d60febc96bffa41f29",
"eventHash1": "0x47224a3068288d010f31d23a0fc22ae2b35021e62576d26380137a3e4f49ef7d",
"eventHash2": "0xdacacdea7188cf128887c926de45696387094969e9c9c81e674f37f1a49be546",
"document": {
"hash": "0xdacacdea7188cf128887c926de45696387094969e9c9c81e674f37f1a49be546",
"owner": "0xEb729A5bB788C87888fD23e4b247b1A0EFc06d2B",
"annoucer": "0xEb729A5bB788C87888fD23e4b247b1A0EFc06d2B",
"meta": "0x6f796269643a406f79622e746563681111111111111111111111111111111111",
"next": "0x000000000000000000000000000000000000000000000000000000000000dead"
}
}],
"contractAddress": "0xA7d9cE4C7Aff81022F639045f4d47241334cdabc",
"network": "polygon-mumbai",
"scanOptions": {
"fromBlock": 21865431,
"toBlock": 22613776,
"topics": ["0x09e614228c98581d113dac6d91007cd6b3b7586704dffc7f61374b860c7fb9c4",
"0x47224a3068288d010f31d23a0fc22ae2b35021e62576d26380137a3e4f49ef7d"],
"contractAddress": "0xA7d9cE4C7Aff81022F639045f4d47241334cdabc"
}
}
The event structure reports the following info:
- type: any of the event type (announce, supersede, retract)
- blockNumber, blockTimestamp, transactionHash: block number, timestamp, and the transaction that generated the event
- eventHash1: is always the origin document hash
- eventHash2: if the event is supersede or announce, the hash value it’s the new document hash. If the event is retracted, the value is the hash of the retracted document
- document: when the event type is announce or supersede, document will contain the attributes of the new document. When a document is retracted, document will contain the attributes of the document that was retracted.
The scan option structure reports the parameters used during the scan, these parameters are passed to the Web3.eth.get_logs() method. Please check Python Web3 documentation for more details.