Publishing through the Known API

Posted on January 07, 2015 in Dev • 6 min read

As stated in my last article, I’m considering moving my blog to Known. But I’m not a huge fan of WSIWYG editors. I find it handy sometimes, and can enjoy editing in Markdown on Github, but for a long post, I really prefer writing content on my own text editor and sending it online after. Plus I can maintain drafts this way and benefits from spell checking abilities with my dictionary.

My goal is then to find a way to post to Known from my own PC, using some kind of local app or script.

That’s really really easy in fact, as every single URL in Known is also an API endpoint.

But, first, let’s talk about a standard way of doing it, that is not Known specific. You can install the IndiePub plugin in Known to enable a MicroPub endpoint in Known.

Note: Take care of cloning the repo correctly in IdnoPlugins as the case matters. Indeed, I cloned it as indiepub (lower case) and it took me some time to figure out why it was not working. After having renamed the folder IndiePub everything works fine.

Micropub is a standard way of publishing content to another website, so that, after having received an authorization from you, an app can publish content to your website. Some kind of standard (part of the IndieWebCamp stuff) API, like the one used by apps on silos to post things on your page.

Then, you can use anything that speaks the Micropub to publish on your website. The most famous one may be Quill, a webapp by aaronparecki. Most of the available tools are written in PHP, but you can also find some libs in Python to handle this kind of stuff (although there does not seem to be any Micropub publishing libraries at the moment).

But known also offers its own API which may be way easier to use, at least to start with. It can be used in basically the same way, but you don’t have to worry as much about authentication and endpoints discovery.

So, every URL endpoint is also an API endpoint. For instance, on your Known homepage, if you click on “status update” to post a new status update, and have a look at the form that appears, you will notice that it posts data to /status/edit (actually, when you click the “status update” button, you will notice there is a link on it to /status/edit, in case you do not have JS enabled). The form is a POST form and you have a body textarea. Let’s try to have a look at the page at status/edit (with your browser). As you can see, you have the same form that allows you to publish a new status. But you can also directly send a query to this address, to post a new entry.

For this purpose, you will have to go to your Settings, in the “Tools and apps” menu and get your API key. Then, you must authenticate every query you send to the API. To this purpose, Known uses a HMAC signature, to prevent from sending the API key in plaintext over the network. Your API key is private and should be kept secret on your side. You will have to create a HMAC signature, using sha256, of the URL you query, thanks to your API key. Snippets to do this in many languages are available here. In these snippets, message is the API endpoint you query (for instance /status/edit in our previous example) and key is your API key.

Then, you have to add specific headers to your query to authenticate. These are X-KNOWN-USERNAME which should be equal to your Known username and X-KNOWN-SIGNATURE which should be set to the previously computed signature. This can be done very easily with curl thanks to the command (updating the values of the headers to the correct one)

$ curl -H "X-KNOWN-USERNAME: USERNAME" -H "X-KNOWN-SIGNATURE: SIGNATURE" http://known.example.org/status/edit

For quick tests of the API, you can use the API Tester plugin, which will take care of forging the correct query based on your inputs. Then, you do not have to worry about building a HMAC signature and so on. You can also use it to check that the requests you send have valid signature (by comparing the generated one and yours) and so on.

Then, you have to send a payload beside the headers. This payload will be the actual content that will be posted. You should pass it as a JSON encoded array (but you can also use other formats, see the API Tester plugin or directly the source code), as it is the easiest way. You should send it with POST.

Let’s have a look in details at our previous example, status update posting, via /status/edit. As we saw, the basic thing to send is the actual content of the status update, through the body field. Then, to post a “blah” status, the JSON encoded payload would look like

{"body": "blah"}

And you can post it with the following curl command:

$ curl -H "X-KNOWN-USERNAME: USERNAME" -H "X-KNOWN-SIGNATURE: SIGNATURE" -X POST --data '{"body": "blah"}' http://known.example.org

And here we go ! Your first status update posted through the API !

Depending on the choosen API endpoint, you might want to pass extra parameters. For example, with “posts” (entry/ in the URLs), you have both a title (logically called title) and a body (as previously). Then, the payload for a post with title “blah” and content “blahblah” will look like

{"title": "blah", "body": "blahblah"}

Most of the endpoints also offer the ability to tweak the created param, to post a content in the paste or in the future (defaults to now). This is what I used to upload the articles from my previous blog to Known, for instance. This parameter is passed to the strtotime PHP function, and should then be in a valid format for this function. Many valid formats are available, including relative ones (see the doc for more info), but the most straight-forward one, with absolute dating, might be to use ISO 8601, that is YYYY-MM-DD HH:MM:SS.

The common endpoints that I have used so far are /status/edit and /entry/edit to post, respectively, status updates and long posts. A working script example (in Python) can be found on my blog repository (taking an entry in the format I used to have for my previous blog, and posting it to Known).

Finally, if you want to use extra endpoints, there is no ready to use doc at the moment (see https://github.com/idno/idno/issues/225 on Github), but the source code is very easily readable, once you know where to look for the infos :) So, you should know that almost everything in Known is an Entity (which is a common way to describe the content you post). Then, all the specific types of Entities (status, long posts, photos, like etc.) are handled by plugins, located in the IdnoPlugins folder. For instance, status are handled by IdnoPlugins/Status and long posts are handled by IdnoPlugins/Text.

Every plugin declares its routes in the Main.php file. For instance, the Status plugin declares the routes /status/edit (post a new status), /status/edit/([A-Za-z0-9]+) (edit an existing status, the last parameter being the id of the status) and /status/delete/([A-Za-z0-9]) (delte a status, same thing as the previous one). Every plugin also declares a content-type which are infos about the type of content it manages, in ContentType.php. Finally, looking in the Pages/ folder, you will find scripts to handle the routes. For instance, for /status/edit, you will find in Pages/Edit.php the associated routes, to get and post content.