Overview

An easy to use API that helps you access the Factom blockchain.

Version information

Version : 1.0.11

URI scheme

Host : api.factom.com
BasePath : /v1
Schemes : HTTPS

Consumes

  • application/json

Produces

  • application/json

Glossary

Directory Block

Unlike in Bitcoin where all blocks are the same, Factom blocks are built with levels and hierarchy. Think of them like Russian nesting dolls where one block can contain many smaller blocks within. The big daddy of each set of blocks is the Directory block. These blocks are created every ten minutes and contain the hashes of all Entry blocks created within that period. These blocks also contain the serial hash of the previous block, allowing them to contribute to the immutability of the Factom blockchain.

Admin Block

Admin blocks make it possible to validate and locate other blocks within the Factom blockchain. The name comes from the fact that the Admin block contains the server signatures of the previous block. These signatures identify the nodes that are writing to the Factom blockchain. In addition, this block tracks the changes to the authority set on the Factom Blockchain; the leader and audit nodes that are empowered to either write to the blockchain or replace a faulty leader. Like the Directory block, the Admin block contains a hash of the previous block. These blocks even have lookup hashes which allow the Factom blockchain to function as a sort of linked list. Just about the only thing these blocks don’t do is bring the coffee. But, we’re working on it…​

Factoid Block

Like bitcoins, factoids can be sent from one wallet to another so long as one has the proper signatures. When this happens, those transactions end up in the Factoid blocks. These blocks contain the input addresses, output addresses, timestamps, and IDs of every factoid or entry credit transaction across the network. Unlike on the Bitcoin blockchain, they aren’t required to carry additional information about the rest of the chain since they sit under the Directory and Admin blocks which handle those essential functions. Pretty nifty.

Entry Block

Entry blocks are where the magic happens in the Factom world. As you may know, the Factom blockchain is made up of a number of Factom chains. Each chain contains a list of entries that have been added to it. When these entries are being packaged by the federated servers, they are arranged by whatever chain they belong to and, viola; an Entry block is born. Entry blocks can contain any non-zero number of entries…​ the only limit is that each entry within must be a part of the same chain. The Merkle root of each of these entry blocks is stored within the directory block that is created at the ten-minute mark. Thus, the cycle begins anew.

Entry Credit Block

Entry Credit blocks are used to track the addition of every entry to the Factom blockchain and to ensure that the correct number of entry credits were paid. These blocks contain the commits and the number of entry credits paid for each of these transactions. Every entry is ordered by when it was received by the federated servers. These will be broken up by the minute markers that are created, surprisingly, every minute.

Address

Addresses on the Factom blockchain are used to send and receive factoids. Each address is protected by a secret key which can be used to initiate transactions with the held factoids. This secret key can also be used in a one-way mathematical calculation to create a public key that can be used to receive factoids. Factoids can be converted into entry credits which can also be held by an Entry Credit address. These entry credits can’t be traded though…​ They can only be used to create new entries on the Factom blockchain.

Merkle Tree

Merkle tree is a tree in which every non-leaf node is labeled with the cryptographic hash of the labels or values (in the case of leaves) of its child nodes. Factom uses Merkle trees to anchor every entry that occurs from every Factom user worldwide into other blockchains. By using this structure, the Factom blockchain can verify and secure its own data with a minimal footprint. This allows the Factom chain to piggyback off of the proof of work created by other blockchains at a very economical cost.

Key Merkle Root

A Key Merkle Root is a Factom data structure which allows for rapid validation of a header. This unique structure combines the Merkle root of a Factom block with the hash of the header of the same block. This way you can validate the header and the block data using just one value. Much in the same way that the Merkle root in the header of a Bitcoin block can prove Bitcoin transactions, the entries of a Factom block can be validated by the Key Merkle root.

About Apollo

Things change fast these days. We live in an era where entire industries can disappear almost overnight. Where the news is fake, your business is in the cloud, and a tweet can change the course of history. In such an uncertain world, it helps to have something you can count on.

Enter Factom. We’ve harnessed cutting-edge technology that allows you to create immutable records. You can have 100% confidence that what you knew yesterday won’t be changed by some hacker tomorrow without your knowledge. And you can still access and verify your critical information from anywhere in the world in an instant. With our data publishing engine, you can lock down any piece of information, time stamp it, and know that it can never be altered or destroyed. In a world where information is the highest form of power, that’s huge.

Our newest innovation is a low-cost way to access this system. Whether you have a set of IoT devices that you need to account for, security camera data that needs to be tamper evident, or even price information that you need to guarantee access to at all times, you can use the Factom Apollo to secure and store that data from anywhere in the world. Our platform can be implemented in minutes and will connect you to the largest network of computers in the world, the Bitcoin blockchain. This guide will give you a quick walkthrough of that process.

Getting Started

Factom Apollo is the shortest distance between you and the Factom blockchain. With a minimal amount of code and development time, you’ll be able to create a permanent and perfect record of any key events and documents you’d like. You or anyone else will be able to prove the existence of those records from anywhere in the world. Once you start using Factom, your documents aren’t secured by the word of some nation or arbiter, but by the laws of nature itself.

drone

So let’s take a look at how you might implement a Factom proof.

Let’s say you have a fleet of delivery drones rolling about the city. You need to make sure you have a public record of where each device was at any given time. You also need to make these records resistant to tampering by hackers or saboteurs. Let’s look at how you can use Factom to create proof of each device’s location that is tamperproof and permanent.

Step 1 - Authentication

To use Apollo, you’ll need to setup an account with Factom. Once you’ve done this, you’ll receive the private key that is used to access Apollo. Please keep this key secure; anyone who has it will be able to make requests from the API in your name. You’ll need to include this key with every request you make to Apollo by attaching the key to the header using the user-key tag. For example:

HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'application/json');
req.setHeader('user-key', '<your-user-key>');

Step 2 - Create Chains

Immutable chains

A "Chain" is a continuous set of records, listed in the order of their creation time. You should create a chain whenever you have a set of documents or files that are all related to the same entity. This entity could be a particular device, in the case of our drone example. It could also represent a single case or client if it involves legal documents. How you use chains is entirely up to you.

What gives a chain its…​ chaineyness™…​ is the fact that each entry is linked. Every entry depends on and thus verifies the entries before it. That means that you can’t make any edits or alterations to a record earlier in the chain without breaking it. Even if you can find an entry you want to change, even if you’re able to muster the computational power needed to alter a blockchain…​ Your tampering will show up like a sore thumb. Creating a chain is a great method for keeping your data clean and secure.

So, let’s create a chain for each of our drones. On Apollo, you do this by making a POST call.

{
  "external_ids":[
    BASE64("DRN00006879"),
    BASE64("UnixTimestamp"),
  ],
  "content": BASE64("Contains the time stamped LatLong coordinates of this drone."),
}

When you create a chain, the content that you send with your request will make up the first entry of that chain. Most Factomizers use this to describe the chain in some way; such as explaining the format of content in the following entries.

You’ll also add the external IDs for the chain to this call. These external IDs will be applied to the chain as well as its first entry. You may want to include some identifiers that can be used along with your internal records to differentiate each chain. In our case, we’re using the serial number for each drone. You may also want to include a unique signature in the content of your entries to validate that they were created by you. The Ed25519 standard works well for this.

Notice that external_ids and content are Base64 Encoded. This is required for all external IDs and any content that is uploaded to Apollo.

If done properly, you should get this response:

HTTP/1.1 202 Accepted
{
  "chain_id": "285904"
}

Cool, one chain down. However, a delivery service with only one drone won’t get you very far. To quote the United States' president: Sad. Let’s add a few more chains to keep you from embarrassing your nation.

{
  "external_ids": [
    BASE64("DRN00006880"),
    BASE64("UnixTimestamp"),
  ],
  "content": BASE64("Contains the time stamped LatLong coordinates of this drone."),
}

Make sure you record the hash (ID) you receive when creating new chains and entries. You’ll want to have a local database that you can use to track IDs and store any data that doesn’t need to be broadcast to the world.

Once you’ve created a chain, we can use additional calls to get information about that chain. Just send a GET call to the chains endpoint along with the ID of the chain you’d like to retrieve.

GET https://api.factom.com/apollo/v1/chains/285904
HTTP/1.1 200 OK
{
  "chain_id": "285904",
  "external_ids": ["RFJONjg3OQ==", "VW5peFRpbWVzdGFtcA=="],
  "links": {
    "entries": "https://api.factom.com/apollo/v1/chains/285904/entries",
    "first": "https://api.factom.com/apollo/v1/chains/285904/entries/first",
    "last": "https://api.factom.com/apollo/v1/chains/285904/entries/last"
  }
}

Not sure about the exact ID of the chain you want? You can also send a GET call with no ID to retrieve all the chains that have been created by your account. If you know the external IDs associated with the chain you want, you can also use the chains/search endpoint to find your chain more quickly. No matter what state your short term memory is in, Apollo has you covered.

Step 3 - Create Entries

Creating Entries is how you can prove events and the execution of documents using Factom. Each event becomes part of a chain of other events relating to the same device or situation. We’d like to keep a permanent record of each of our drones locations in a separate chain so that we prove beyond a shadow of a doubt where they were at any point in history. Time to go to work.

Let’s set up a simple timestamp. We’ll use the external IDs to mark the date and time of the entry for our records. In the content, we’ll store the location of the drone at that point. Your first entry might look something like this:

{
  "external_ids":[
    BASE64("DRN00006879"),
    BASE64("1490785259"),
  ],
  "content": BASE64("30.269453, -97.749889")
}

External IDs can be used like tags to categorize your entries and chains. This gives you another way to relate records to one another outside of including them on the same chain. You can search for either chains or entries by their external ids by using either the POST: /chains/search or POST: /chains/{chain_id}/entries/search endpoints.

And remember: External IDs and Content must be uploaded in Base64!

And the response…​

HTTP/1.1 202 Accepted
{
  "entry_hash":"43E9FB0C56D502056D11A2694F6B68611D5BB6B1AE603862F721E32B45BFC4A4"
}
Adding to a chain

All new entries end up as the last item in the chain. This is enforced by Apollo and also by the logic of the blockchain itself. Because each entry relies on the entries that come before it, trying to add a new entry to the middle of a chain would essentially break it.

Because of this, each entry has an immutable creation time based on when gets added to the chain it belongs to as well as the Factom and other public blockchains. You can recall any entry via its Chain ID and Entry ID by sending a GET call to the entries endpoint.








Example
GET - https://api.factom.com/apollo/v1/chains/285904/entries/43E9FB0C56D502056D11A2694F6B68611D5BB6B1AE603862F721E32B45BFC4A4

Don’t publish any private data using Apollo, even with encryption. Anything sent through the content parameter will remain on the blockchain forever, so it’s safe to assume that someone may decrypt it at some point. When you need to verify data that you can’t afford to store publicly, a hash can work just as well. Create an SHA256 hash of the data and upload that instead. For added security, you can include an Ed25519 signature and a nonce with each upload so you can verify that each entry is genuine.

The first and last entries of a chain have distinct endpoints that can be used to access them. The first entry of a chain is often a descriptive entry that helps you to read the rest of the entries on the chain. It’s often helpful to call this entry as a reference. The last entry is special in that it’s the most recent. It often contains pertinent information and also serves the validate the rest of the chain. Let’s check the last known location of our delivery drone using one of these endpoints.

GET - https://api.factom.com/apollo/v1/chains/285904/entries/last
HTTP/1.1 202 Accepted
{
  "entry_hash": "43E9FB0C56D502056D11A2694F6B68611D5BB6B1AE603862F721E32B45BFC4A4",
  "chain_id": "285904",
  "external_ids": :["TWFyY2g=", "Mjk=", "MjAxNw==", "MTEwMDU5"],
  "content": "MzAuMjY5NDUzLCAtOTcuNzQ5ODg5",
  "links" {
    "chain": "https://api.factom.com/apollo/v1/chains/285904"
  }
}

Great! Now, when your customers want to dispute a delivery (and they will…​) you’ll be able to point to a perfect record that will prove your drone was there on time. The tamper evident aspect of Factom records shines here. To explore this, let’s take a quick look at another case…​

Step 4 - Verify Entries

Using Apollo, you can create tamper evident records by exploiting the immutability of blockchain ledgers. Even if, with all your security and counter measures, some super hacker manages to infiltrate your systems and play canasta with your databases, you still have a way to detect their activity. To demonstrate this, let’s step away from the drone example for a while and check out a completely different scenario…​

Imagine for a moment that you work for a museum. Your job is to set up a security system worthy of protecting millions of dollars worth of historical artwork and artifacts. You’ve strategically placed smart cameras throughout the building so that you can capture images of potential thieves. Each camera is tied to a motion sensor that takes a still shot whenever someone walks in front of it. Enough of these bad boys and even George Clooney can’t pull off a heist.

That is until his hacker friend deletes the footage and leaves you SOL.

Luckily, data that you’ve uploaded to the Factom blockchain is tamper-proof. That means it’s child’s play to see if someone’s corrupted your local records.

Memento
Unfortunately, Factom wasn’t invented in time to help Mr. Shelby…​

First, let’s call back the chain that you’ve assigned to one of the cameras. We know the ID for this chain is 86875. We’ll use the /entries endpoint to get the full list of entries contained in this chain.

GET - https://api.factom.com/apollo/v1/chains/86875/entries
HTTP/1.1 200 OK
{
  "items":
  [
    {
      "entry_hash": "E53884DADE5790F26895621A10BCFC12BB432F9D2684FC2F71CE7BC56A7D47A3",
      "links": {
        "entry": "https://api.factom.com/apollo/v1/chains/86875/entries/E53884DADE5790F26895621A10BCFC12BB432F9D2684FC2F71CE7BC56A7D47A3"
      }
    },
    {
      "entry_hash": "5D6A61D7DD9EBDE4D1479F7A35387154EA79D3FDB4C2C4DBB821C283CABE4123",
      "links": {
        "entry": "https://api.factom.com/apollo/v1/chains/86875/entries/5D6A61D7DD9EBDE4D1479F7A35387154EA79D3FDB4C2C4DBB821C283CABE4123"
      }
    }
    {
      "entry_hash": "6C420F431354A39CD0814A2941003A1E35952CED4250CACD5F721B21F02EEA0A",
      "links": {
        "entry": "https://api.factom.com/apollo/v1/chains/86875/entries/6C420F431354A39CD0814A2941003A1E35952CED4250CACD5F721B21F02EEA0A"
      }
    }
  [...]
  ]
}

Next, we need to call each entry in sequence to get their contents. Here’s one example.

GET - https://api.factom.com/apollo/v1/chains/86875/entries/ea
HTTP/1.1 200 OK
{
"entry_hash": "43E9FB0C56D502056D11A2694F6B68611D5BB6B1AE603862F721E32B45BFC4A4",
"chain_id": "285904",
"external_ids": ["NkQ3OQ==", "NkU2NTc3", "NjM2ODYxNjk2RQ==", "NjU2RTc0NzI3OQ=="],
"content": "{Image Hash}",
"links" {
   "chain": "https://api.factom.com/apollo/v1/chains/86875"
   }
}

Image data is both extremely large and potentially sensitive; both no-nos for uploading to a blockchain. Hence, we’ve uploaded hashes instead of the raw data. Keep your uploads small and, if it’s private, keep it between you and the NSA.

The Hash value of each entry in your database should match an entry in the chain. If you see one that doesn’t match, you can assume that someone has tampered with that data. You may also come across a situation where there’s an extra entry that’s been signed but doesn’t have a matching image in the database. This evidence most likely means that your intruder has deleted the local files. Since data stored to the blockchain is locked chronologically, you can discover when the missing image originally got uploaded. You know what the attacker altered, and you have a window of when your system was accessed. Not too shabby.

Bonus Round - Callbacks

Throughout this introduction, you’ve probably been asking yourself some questions: How does immutability work? Is my data backed up by anything other than Factom? Where did you guys find a psychic writer? We’ll answer some of these here.

Apollo backs up your entries in three places. One is a standard database. The other two are blockchains. Not all of these are written at the same time though. While anyone with permission can change database entries on a whim, blockchains are a little trickier. The entire community has to come to a consensus before any changes can be considered permanent. For the Factom blockchain, this happens every ten minutes. But for other blockchains, the lag time may vary.

Luckily, Apollo lets you know where you stand regarding immutability. As your entries get replicated across the network, we’ll send you a POST request to notify you of where we’ve saved your data. All it takes is to add a few additional fields when you create the entry. Let’s check it out:

{
  "external_ids": ["bXk=", "bmV3", "Y2hhaW4=", "ZW50cnk="],
  "content": "U29tZSBiYXJlIGNvbnRlbnQK",
  "callback_url": "http://httpbin.org/post/?my_id=12345",
  "callback_stages": ["factom"]
}

When setting your callback_url, it’s a good idea to include some sort of identifier so you know which entity the callback is referring to. If you include this as a query parameter, Apollo will see this and adjust its output accordingly. In the example above, we’ve used my_id as our parameter and set it to 12345. In practice, you can enter whatever parameters and values you like.

As you can see, there are two fields that are added when you want to use callbacks: callback_url, and callback_stages. As long as callback_url is set, you’ll get a callback from Apollo in the form of a POST request to the URL you entered. You’ll also be able to tell Apollo when you want to get updated via the callback_stages field. If you don’t include the callback_stages field, it will default to "{factom, bitcoin}".

Speaking of which, let’s check out that callback response.

POST - http://httpbin.org/post/?my_id=12345&dblock_keymr=<some-hash>&stage=factom
{}

You’ve probably noticed that the POST request has no body parameters. It does, however, include information in the query. The stage parameter is always added and represents the stage of immutability that your entry has reached. The other parameter will be either entry_hash, dblock_keymr, or bitcoin_block_hash depending on the stage.

For more information about callback stages, check the out the callback section.

Apollo Sandbox

One thing you’ll notice about blockchain technology: everything is forever. Every mistake, every misstep is recorded for all eternity. That’s fine when you’re dealing with a finished product. It’s not so good when you’re in development and still working the kinks out. But worse still, writing entries has a cost. Testing a new feature on a live blockchain would mean burning real money to store your test data. Plus, having your test entries in the public realm could give competitors insight into your operations. When you’re building out your new platform and testing things out, it’d be nice to have a way to work on your solution and get things right without making a big immutable mess of the Factom blockchain.

To help out, we’ve created a sandbox area for development and testing. The sandbox uses a separate database and connects to a duplicate version of the Factom blockchain called a Testnet. There’s no anchoring or immutability on this chain, but otherwise, it functions exactly like the main blockchain. Testnets are transient; the Apollo sandbox will create and destroy these blockchains as needed by the users. Also, access to these blockchains is restricted. No need to worry about sensitive data accidentally leaking and becoming public knowledge. This makes the Apollo sandbox the perfect place to test out your software.

You’ll get access to the Sandbox once you sign on for Apollo access. From that point forward you’ll have unlimited use of its facilities.

Remember, entries and chains that you create in the sandbox will not be saved. We’ll delete the data stored here at regular intervals to keep things running smoothly. In other words, don’t use this sandbox area for demos, proofs of concepts, or anything else where you may want to have your records maintained.

Think of it as a hotel. You can use it as you wish and we’ll clean up after you…​ but you leave things behind at your own risk.

Example: Documents

So at this point, you may be thinking: “But Factom, I don’t have a bunch of IoT devices…​ Apollo must not be for me.” It’s OK. We understand. We were wrong once too, back in the 90’s. We know what it’s like. And we’re here to help you see the light.

See, one of the best uses for Apollo is to help you secure documents. Anything that can be destroyed, altered, doctored or lied about can also be secured by the Factom blockchain. This will give you indisputable proof that a particular document existed in a particular state at a given time. How does it work? To find out, let’s venture away from technology a bit and enter the world of expression.

Leonardo di Pacifico
You call that Chiaroscuro? Garbage!

Art is one of those cornerstones of human civilization. It’s ostensibly what makes human beings the enlightened creatures we say we are. Sure, there may be other animals who can see infrared and ultraviolet light or sleep with half of their brain and swim with the other half…​ But until they have a Picasso, I think we have them beat.

Our system for tracking these valuable pieces, however, is frighteningly obsolete. Every piece of artwork can have an entirely different format for its certificate. As a result, there’s no real way to verify that what you’re looking at is authentic. Still, $45 Billion dollars worth of art was moved just last year based on the word of these flimsy certificates. An entire industry built entirely on faith. It’s the perfect chance for Factom to make the world’s systems honest.

So, let’s say you want to bring some order to this madness. There are a few things you’ll have to take care of first. As our chief scientist, Brian Deery, notes in our blog: paper records have hung around for a reason. You can’t forge them on a massive scale in the same way you could with a digital record. With paper, you need to have the right materials, processes, and information to create a decent fake. But once you move to a digital record, all you need is access to the right computer. Once a hacker gains access to a system, he effectively invalidates EVERY document that system has ever created. You can’t be sure which ones are real and which are fake.

With Apollo, that problem is solved. As soon as the organization issues a document, they can just create a record on the Factom blockchain to go with it. There’s still a risk that someone will compromise your system and create fake records, but Apollo will ensure that your past records are preserved. If you know when the breach took place, you can assume everything created before that point in time is still valid.

What does that look like in practice? To find out, let’s check out the newest player in the Artwork authentication scene, Art Dudes Incorporated. Art Dudes has created a simple system whereby artists and sellers can secure their certificates of authenticity. Users will be able to create and transfer certificates without needing to trust each other or even Art Dudes. All trades and transfers will be documented using the Factom blockchain to provide immutable evidence of the history of a particular work of art in a way that is transparent and auditable by third parties. But to make sure that Art Dudes doesn’t hold undue influence over these records, they need to put the power to secure transactions in the hands of the users. Luckily, there’s math for that.

Gettin' Siggy With It

The Factom blockchain has two traits that are both critical to making it work and very difficult for some models to work around: First, it’s transparent and second, it’s uncensored. Transparency means that anyone can audit the records. There’s no way for anyone, even Factom, to lie about the data. What’s there is there for all the world to see. This is perfect for the case of what we’re building here since it means that there’s no need to trust these certificates. You can verify them yourself. It’s the second part complicates things…​

The Blockchain Abides

Lebowski

The Factom blockchain is designed to be free of censorship. That means no one in the world has the power to prevent anyone from publishing the data of their choice. This is great for creating a fair and transparent publishing method, but it also means that anyone can publish to your chains. The federated servers are strickly neutral parties. They don’t care who you are or what you post. If you’ve got the credits, they’ve got the entries. So what’s to stop some big mean mother hubbard from making fake trades on your chains and wrecking your carefully constructed proof of provenance?

The answer? Use a Signature.

By signing your entries with a private key, you can ensure that even if someone publishes fake data to your chain, you can spot it and ignore it. Similarly, if you want to spoof your own chain to obscure your data, signatures can help you secretly separate the real from the benign. There are a number of algorithmic options available for signing transactions. Curve25519, ECDSA, RSA…​ For the purposes of this demonstration, we’re going to work with the ED25519 standard. You can read more about it here: https://ed25519.cr.yp.to/

Private Keys

To use a signature, you first need a private key. This the secret that you will use the generate the other values we’ll talk about shortly. In the Art Dudes portal, the private keys are held by the users who will use them to sign their entries and transactions.

Public Keys

The Public Key is how you can broadcast your identity safely on a blockchain or similar cryptographic system. This value is derived from your public key and can be used to prove that two hashes were made with the same private key’s signature. In the Art Dudes portal, Public Keys will be broadcast when new artists are created and when a work of art is transferred from one user to another.

Signing Transactions

A signature is generated when you take your private key and run in through a signing algorithm. This algorithm only works in one direction; having the signature does not allow you to derive the private key that created it. You can, however, prove that whoever did generate the signature had the proper key by checking the signature against the Public Key.  Once you have your signature, you can hash the entry with it in order to prove that you have the correct private key without exposing that key.

Creating an Artist

So now that that’s covered, it’s time to sign up our first Artist. Since every artist uses their own choice of COA, we can’t count on knowing what format his certificate is in. Instead, we’ll focus on making sure we know who the artist is and that we can prove when he’s authorized something and not some random interloper. So when an artist creates a profile on Art Dudes.com, she get’s a private key to go with it. This key in known only to her. Neither Factom or Art Dudes or her ISP or any other company involved in this transaction needs to know her private key. They only thing she’s going to broadcast is her public key. This key will be stored in an entry using Apollo along with some details about the artist. The portal will add this entry to the User chain that has already been created by Art Dudes.

{
  "external_ids": [
    BASE64("Spears, S"),
    BASE64("{Public Key}"),
    BASE64("UnixTimestamp")
  ],
  "content": BASE64("Name: Sasha Spears; Nationality: France")
}

A New Work of Art

But the Artist didn’t sign up for her health. She’s here to make the arduous journey from starving artist working as a barista to an artist who can afford to buy coffee made by a barista. That means she’s got to move some artwork. To keep that resale value high, she’s going to need to start the chain of provenance. Conveniently, Factom also has chains. So we’ll create one for this piece.

The first entry in the chain will have the details about the painting as well as the signature of the artist and a link to her entry on the User chain. This way we know that the Artist in question really did create this work of art. We’ll also include a document number which will tie back to the physical Certificate of Authenticity.

{
  "external_ids":[
    BASE64("Spears, S"),
    BASE64("2813308004"),
    BASE64("UnixTimestamp")
  ],
  "content": BASE64("Title: The Man in the Yellow Hat; Medium: Oil Paint; Canvas: 30*40; Artist: Sasha Spears; COA: 2813308004; {Artist_Signature}")
}

Once that’s done, we’ll need to create a link to this chain in the User chain. This will allow anyone who is looking at the data for the artist to easily find the chain related to this new piece. The process should look familiar to you.

{
  "external_ids": [
    BASE64("Spears, S"),
    BASE64("{Public Key}"),
    BASE64("UnixTimestamp")
  ],
  "content": BASE64("New Artwork: {art_chain_hash}; {artist_signature}")
}

And viola! One blockchain enhanced COA. The artist can use whatever document she wants and even reproduce that document if it is damaged or destroyed. As long as what it says matches the immutable record created by Apollo, her customer will know it’s genuine. Speaking of customer’s let’s get this thing sold.

Transfer of Ownership

Transferring the art to a new owner is similar to creating the piece of art in the first place. As before, you’ll need to include the signature of the current owner. In this case, it’s the original artist. You’ll also want to include a link to the previous entry in the chain. This way you can easily skip over unauthorized or unrelated entries. It’ll also help you in cases where there are multiple legitimate copies of a certain piece. Finally, you’ll include the public key of the new owner. This person will need to have created an entry on Art Dudes User chain so you can link to that as well. When you get done, the entry will look something like this:

{
  "external_ids": [
    BASE64("Spears, S"),
    BASE64("2813308004"),
    BASE64("UnixTimestamp")
  ],
  "content": BASE64("Ownership Transfer: {new_owner_public_key}; New Owner: {owner_entry_hash}; Original Owner: {artist_entry_hash}; {artist_signature}")
}

With every new change of ownership, you simply repeat the process. The old owner signs the artwork over to the new owner. Any entries without valid signatures are ignored. And the end result is a perfect and permanent record of every time every piece of art that you’re tracking has changed hands. No matter what different forms of paper COAs are used, you can always validate them using the Factom blockchain.

Paths

GET /

Description

Request all information about the endpoint

Responses

HTTP Code Description Schema

200

OK

AllInfo

Example HTTP request

Request path
/

Example HTTP response

Response 200
{
  "api_version" : "v1.0.1234",
  "links" : {
    "chains" : "https://api.factom.com/apollo/v1/chains"
  }
}

POST /chains

Description

Create a new chain. Each chain functions as a mini-blockchain such that all of the entries are linked. Every entry relies on data from previous entries in the chain. Any unauthorized alterations to any of these entries can be detected. Be aware that data entered into the content and external_ids fields must be in Base64 format. Sending this request will cause Apollo to create the first entry of the chain. The data entered into the content and external_id fields will be applied to this entry.

Body parameter

Name : ChainContent
Flags : required
Type : ChainCreate

Responses

HTTP Code Description Schema

202

Accepted

Response 202

Response 202

Name Description Schema

chain_id
optional

The Chain ID of the chain that you just created. You may use this unique ID to find or add to this chain in the future.
Example : "string"

string

Example HTTP request

Request path
/chains
Request body
{
  "external_ids" : [ "bXk=", "Y2hhaW4=" ],
  "content" : "VGhpcyBpcyB0aGUgY29udGVudCBvZiB0aGUgZmlyc3QgY2hhaW4gZW50cnk=",
  "callback_url" : "http://httpbin.org/post?my_id=\"12345\"",
  "callback_stages" : [ "factom", "bitcoin" ]
}

Example HTTP response

Response 202
{
  "chain_id" : "285904"
}

GET /chains

Description

Returns all of the chains on factomd.

Responses

HTTP Code Description Schema

200

OK

Response 200

Response 200

Name Description Schema

items
optional

Example : [ "ChainLink" ]

< ChainLink > array

Example HTTP request

Request path
/chains

Example HTTP response

Response 200
{
  "items" : [ {
    "chain_id" : "285904",
    "links" : {
      "chain" : "https://api.factom.com/apollo/v1/chains/285904/"
    }
  } ]
}

POST /chains/search

Description

Finds all of the chains with external_ids that match what you’ve entered. External IDs must be sent in Base64 format.

Body parameter

Name : body
Flags : required
Type : ExternalIds

Responses

HTTP Code Description Schema

200

OK

Chain

Example HTTP request

Request path
/chains/search
Request body
{
  "external_ids" : [ "bXk=", "Y2hhaW4=" ]
}

Example HTTP response

Response 200
{
  "chain_id" : "285904",
  "external_ids" : [ "bXk=", "Y2hhaW4=" ],
  "links" : {
    "entries" : "https://api.factom.com/apollo/v1/chains/285904/entries",
    "first" : "https://api.factom.com/apollo/v1/chains/285904/entries/first",
    "last" : "https://api.factom.com/apollo/v1/chains/285904/entries/last"
  }
}

GET /chains/{chain_id}

Description

Get information about a specific chain on Apollo

Parameters

Type Name Description Schema

Path

chain_id
required

Chain identifier

string

Responses

HTTP Code Description Schema

200

OK

Chain

Example HTTP request

Request path
/chains/285904

Example HTTP response

Response 200
{
  "chain_id" : "285904",
  "external_ids" : [ "bXk=", "Y2hhaW4=" ],
  "links" : {
    "entries" : "https://api.factom.com/apollo/v1/chains/285904/entries",
    "first" : "https://api.factom.com/apollo/v1/chains/285904/entries/first",
    "last" : "https://api.factom.com/apollo/v1/chains/285904/entries/last"
  }
}

POST /chains/{chain_id}/entries

Description

Create a new entry for the selected chain. Content and extrenal id must be uloaded in Base64 format.

Parameters

Type Name Description Schema

Path

chain_id
required

Chain identifier

string

Body parameter

Name : EntryContent
Flags : required
Type : EntryCreate

Responses

HTTP Code Description Schema

202

Accepted

Response 202

422

Unprocessable entity

object

Response 202

Name Description Schema

entry_hash
optional

The SHA256 Hash of the entry you just created. You can use this hash to referece this entry in the future.
Example : "string"

string

Example HTTP request

Request path
/chains/285904/entries
Request body
{
  "external_ids" : [ "bXk=", "bmV3", "Y2hhaW4=", "ZW50cnk=" ],
  "content" : "V2FpdCwgYXJlIHlvdSByZWFsbHkgdGFraW5nIHRoZSB0aW1lIHRvIGNvbnZlcnQgdGhlc2UgYW5kIHJlYWQgdGhlbT8gV293Lg==",
  "callback_url" : "http://httpbin.org/post?my_id=\"12345\"",
  "callback_stages" : [ "factom", "bitcoin" ]
}

Example HTTP response

Response 202
{
  "entry_hash" : "db"
}
Response 422
"object"

GET /chains/{chain_id}/entries

Description

List all entries contained on the specified chain.

Parameters

Type Name Description Schema

Path

chain_id
required

Chain identifier

string

Responses

HTTP Code Description Schema

200

OK

Response 200

Response 200

Name Description Schema

items
optional

Example : [ "EntryLink" ]

< EntryLink > array

Example HTTP request

Request path
/chains/285904/entries

Example HTTP response

Response 200
{
  "items" : [ {
    "entry_hash" : "ea",
    "links" : {
      "entry" : "https://api.factom.com/apollo/v1/chains/285904/entries/ea"
    }
  }, {
    "entry_hash" : "ce",
    "links" : {
      "entry" : "https://api.factom.com/apollo/v1/chains/285904/entries/ce"
    }
  } ]
}

GET /chains/{chain_id}/entries/first

Description

Retrieve the first entry that has been saved to this chain.

Parameters

Type Name Description Schema

Path

chain_id
required

Chain identifier

string

Responses

HTTP Code Description Schema

200

OK

Entry

Example HTTP request

Request path
/chains/285904/entries/first

Example HTTP response

Response 200
{
  "entry_hash" : "ea",
  "chain_id" : "285904",
  "external_ids" : [ "NkQ3OQ==", "NjM2ODYxNjk2RQ==" ],
  "content" : "aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1xSjdZQWh0elJzWQ==",
  "links" : {
    "chain" : "https://api.factom.com/apollo/v1/chains/285904"
  }
}

GET /chains/{chain_id}/entries/last

Description

Retrieve the last entry that has been saved to this chain.

Parameters

Type Name Description Schema

Path

chain_id
required

Chain identifier

string

Responses

HTTP Code Description Schema

200

OK

Entry

Example HTTP request

Request path
/chains/285904/entries/last

Example HTTP response

Response 200
{
  "entry_hash" : "ea",
  "chain_id" : "285904",
  "external_ids" : [ "NkQ3OQ==", "NjM2ODYxNjk2RQ==" ],
  "content" : "aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1xSjdZQWh0elJzWQ==",
  "links" : {
    "chain" : "https://api.factom.com/apollo/v1/chains/285904"
  }
}

POST /chains/{chain_id}/entries/search

Description

Find all of the entries wihin the specified chain that have the requested external_ids.

Parameters

Type Name Description Schema

Path

chain_id
required

Chain identifier

string

Body parameter

Name : body
Flags : required
Type : ExternalIds

Responses

HTTP Code Description Schema

200

OK

Entry

Example HTTP request

Request path
/chains/285904/entries/search
Request body
{
  "external_ids" : [ "bXk=", "Y2hhaW4=" ]
}

Example HTTP response

Response 200
{
  "entry_hash" : "ea",
  "chain_id" : "285904",
  "external_ids" : [ "NkQ3OQ==", "NjM2ODYxNjk2RQ==" ],
  "content" : "aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1xSjdZQWh0elJzWQ==",
  "links" : {
    "chain" : "https://api.factom.com/apollo/v1/chains/285904"
  }
}

GET /chains/{chain_id}/entries/{entry_hash}

Description

Returns information about a specific entry on Apollo

Parameters

Type Name Description Schema

Path

chain_id
required

Chain identifier

string

Path

entry_hash
required

The SHA256 hash of the entry.

string

Responses

HTTP Code Description Schema

200

OK

Entry

Example HTTP request

Request path
/chains/285904/entries/db

Example HTTP response

Response 200
{
  "entry_hash" : "ea",
  "chain_id" : "285904",
  "external_ids" : [ "NkQ3OQ==", "NjM2ODYxNjk2RQ==" ],
  "content" : "aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1xSjdZQWh0elJzWQ==",
  "links" : {
    "chain" : "https://api.factom.com/apollo/v1/chains/285904"
  }
}

Callbacks

HOOK /{callback_url}

Description

Informs you about the status of an entry or chain. To activate this callback, include a callback_url field when creating your entry or chain. The callback response will include query parameters that will tell you the current stage of your entry and will give you a stage specific reference to help you locate your entry.

For a more comprehensive guide on the use of callbacks, read our introduction.

Callback Stages

Apollo can be set to notify you at three different stages of durability. You can select which stages you would like to be notified of by including the requested stages in the callback_stages field when you are creating a new chain or entry. You may include a single stage or multiple stages as you wish. The possible stages are as follows:

multi_az

This stage means your entry or chain exists in multiple availability zones in the Apollo database. Your data isn’t immutable quite yet; it’s not stored on a blockchain. However, you’ve got replication across our networks as well as your local storage. When getting back your POST request, it’ll include the entry_hash as one of the query parameters as well as the stage. This is the actual SHA256 hash of your entry.

factom

The entry has been submitted to a factom block and has been subsequently confirmed by the network. Your entry now exists in two different places: a replicated database and the Factom blockchain. If you include this string under callback_stages, you’ll be sent a POST request with the stage as well as the dblock_keymr. dblock_keymr stands for Directory Block Key Merkle Root. You can use this to identify the Factom directory block where Apollo has stored your entry.

bitcoin

Your entry reaches the final stage when we anchor it to the Bitcoin blockchain. Once this happens, your entry exists in two immutable blockahins and is nearly impossible to alter. The callback message will include the bitcoin_block_hash of your entry as one of the query parameters. You can use this hash to locate the block that contains your Factom anchor in the Bitcoin blockchain.

Example HTTP request to initiate callback

Request path
/chains/285904/entries
Request body
{
  "external_ids" : [ "bXk=", "bmV3", "Y2hhaW4=", "ZW50cnk=" ],
  "content" : "V2FpdCwgYXJlIHlvdSByZWFsbHkgdGFraW5nIHRoZSB0aW1lIHRvIGNvbnZlcnQgdGhlc2UgYW5kIHJlYWQgdGhlbT8gV293Lg==",
  "callback_url" : "http://httpbin.org/post?my_id=\"12345\"",
  "callback_stages" : [ "multi_az", "factom", "bitcoin" ]
}

Callback Request

POST {callback_url}/?entry_hash="{entry_hash}"&stage="multi_az"

or

POST {callback_url}/?dblock_keymr="{dblock_keymr}"&stage="factom"

or

POST {callback_url}/?bitcoin_block_hash="{bitcoin_block_hash}"&stage="bitcoin"

Example HTTP Callback request

Request path
POST - http://httpbin.org/post/?my_id=12345&dblock_keymr=<some-hash>&stage=factom
Request body
{}

Definitions

AllInfo

Name Description Schema

api_version
optional

Apollo version
Example : "string"

string

links
optional

Links to internal paths of the application
Example : "object"

links

Name Description Schema

chains
optional

Link to chain api
Example : "string"

string

Chain

Represents a list of Factom entries that have been or will be saved to the blockchain.

Name Description Schema

chain_id
optional

This is the unique identifier created for each chain.
Example : "string"

string

external_ids
optional

Tags that can be used to identify your entry. You can search for records that contain a particular external_id using Apollo. You must send External IDs in Base64 format.
Example : [ "string" ]

< string > array

links
optional

Example : "object"

links

Name Description Schema

entries
optional

URL of the list of Entries of a given Chain
Example : "string"

string

first
optional

URL of the first Entry of a given Chain
Example : "string"

string

last
optional

URL of the last Entry of a given Chain
Example : "string"

string

ChainCreate

Used to create a new chain on Apollo.

Name Description Schema

callback_stages
optional

The stages that you would like to trigger a callback from Apollo. This list can include any or all of the three stages: multi_az, factom, and bitcoin. If callbacks are activated and this field is not sent, it will default to factom and bitcoin
Example : [ "string" ]

< string > array

callback_url
optional

The URL where you would like to receive the callback from Apollo. If this is null, callbacks will not activate.
Example : "string"

string

content
optional

This is the data that will make up the first entry in your new chain. It is customary to use this space to describe the entries that are to follow in the chain. You must send the content field in Base64 format.
Example : "string"

string

external_ids
optional

Tags that can be used to identify your chain. You can search for records that contain a particular external_id using Apollo. You must send External IDs in Base64 format.
Example : [ "string" ]

< string > array

An object that contains the Chain Hash (ID) as well as a URL for the chain.

Name Description Schema

chain_id
optional

This is the unique identifier created for this chain.
Example : "string"

string

links
optional

Example : "object"

links

Name Description Schema

chain
optional

Example : "ChainURL"

ChainURL

ChainURL

You can send an authenticated GET request to this URL to retrieve information about the specified chain.

Type : string

Entry

A single record that has been or will be saved to the blockchain.

Name Description Schema

chain_id
optional

This is the unique identifier created for each chain.
Example : "string"

string

content
optional

This is the data that is stored by the entry. Content will be sent in Base64 format.
Example : "string"

string

entry_hash
optional

The SHA256 Hash of this entry.
Example : "string"

string

external_ids
optional

Tags that can be used to identify your entry. You can search for records that contain a particular external_id using Apollo. External IDs are returned in Base64.
Example : [ "string" ]

< string > array

links
optional

Example : "object"

links

links

Name Description Schema

chain
optional

Example : "ChainURL"

ChainURL

EntryCreate

This information will be used to create a new entry.

Name Description Schema

callback_stages
optional

The stages you’d like to be notified about. This list can include any or all of the three stages: multi_az, factom, and bitcoin. If callbacks are activated and this field is not sent, it will default to factom and bitcoin
Example : [ "string" ]

< enum (multi_az, factom, bitcoin) > array

callback_url
optional

The address you’d like the callback to be sent to. If this is null, callbacks will not activate.
Example : "string"

string

content
optional

This is the data that will be stored directly on the blockchain. Please be sure that no private information is entered here. Content should be sent in Base64 format.
Example : "string"

string

external_ids
optional

Tags that can be used to identify your entry. You can search for records that contain a particular external_id using Apollo. External IDs should be sent in Base64.
Example : [ "string" ]

< string > array

An object that contains the Entry Hash (ID) and a URL for the entry.

Name Description Schema

entry_hash
optional

The SHA256 Hash of this entry.
Example : "string"

string

links
optional

Example : "object"

links

Name Description Schema

entry
optional

Example : "EntryURL"

EntryURL

EntryURL

You can send an authenticated GET request to this url to retrieve information about the specified entry.

Type : string

ExternalIds

The external IDs of the chains or entries you want to retrieve. You must enter these External IDs in Base64 format.

Name Description Schema

external_ids
optional

A list of external IDs.
Example : [ "bXk=", "Y2hhaW4=" ]

< string > array

Status Codes

200 - OK

Your request was executed successfully.

201 - Created

Your request was executed, and new data has been created.

204 - No Content

Your request was received, but there is no data to return.

Error Codes

400 - Bad Request

The data received is invalid or incorrectly formatted (e.g. invalid JSON).

401 - Unauthorized

Login Failed. The user is not authorized to create a session.

403 - Authentication Failed

The Authorization Token you entered is not valid. Please check your Token and try again.

403 - Authentication Parameters Missing

There was no authentication data passed with this call. Please make sure you include your Authorization Token in every call to Apollo.

404 - No Mapping Rule Matched

This error means that the attempted call did not match anything that Apollo could recognize. Check the format of your entry and make sure you are targeting the correct endpoint.

404 - Page Not Found

The ID you entered did not match a known chain or entry. Please check the ID and try again.

415 - Unsupported Media Type

The content that you sent is not supported by this API. Please use a compatible format.

422 - Unprocessable entity

The syntax and format of the request were correct, but Apollo was unable to process the contained instructions. Please contact support for more assistance.

500 - Internal Error

There was an error that prevented Apollo from addressing your request. Please contact support for more assistance.

Change Log

Version 0.9.1: September 1st, 2017

Added

Section Change

Apollo Sandbox

Added information about the sandbox.

Changed

None

Removed

Section Change

Security

The Security section has been removed. Information about authentication can be found in the Getting Started guide.


Version 0.9.0: October 23rd, 2017

Added

None

Changed

Section Change

Overview

Removed apollo from base path.

POST /chains

async field no longer used.

POST /chains/{chain_id}/entries

async field no longer used.

Removed

None


Version 0.8.6: September 14th, 2017

Added

Section Change

Example

Added New Example

Changed

None

Removed

None


Version 0.7.1: July 25th, 2017

Added

Section Change

Overview

Added Glossary

Callbacks

Added Callback Stages List

Callbacks

Added Callback URL Explaination

Changed

Section Change

POST /chains

Clarified chain creation.

Removed

Section Change

Getting Started

Callback stages list has been removed.