Posting to Discourse via the Discourse REST API from Python

The Bad Voltage forum is run by Discourse. As part of posting a new episode, I wanted to be able to send a post to the forum from a script. Discourse has a REST API but it’s not very well documented, at least partially because it’s still being worked on. So if you read this post two years after it was written, it might be entirely full of lies. Still, I managed to work out how to post to Discourse from a Python script, and here’s an example script to do just that.

First, you’ll need an API key. If you’re the forum administrator, which I am, you can generate one of these from http://YOURFORUM/admin/api. It is not clear to me exactly what this API key does: in particular, I suspect that it is a key with total admin rights over the forum, so don’t share it around. If there’s a way of making an API key with limited rights to just create posts and that’s it, I don’t know that way; if you do know that way, tell me! Once you’ve got your API key, and your username, fill them into the script as APIKEY and APIUSERNAME.

import requests # apt-get install python-requests
# based on https://github.com/discoursehosting/discourse-api-php/blob/master/lib/DiscourseAPI.php

# log all the things so you can see what's going on
import logging
import httplib
httplib.HTTPConnection.debuglevel = 1
logging.basicConfig() 
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

# api key created in discourse admin. probably super-secret, so don't tell anyone.
APIKEY="whatever the api key is"
APIUSERNAME="your username"
QSPARAMS = {"api_key": APIKEY, "api_username": APIUSERNAME}
FORUM = "http://url for your forum/" # with the slash on the end

# First, get cookie
r = requests.get(FORUM, params=QSPARAMS)
SESSION_COOKIE = r.cookies["_forum_session"]

# Now, send a post to the _forum_session
post_details = {
    "title": "Title of the new topic",
    "raw": "Body text of the post",
    "category": 7, # get the category ID from the admin
    "archetype": "regular",
    "reply_to_post_number": 0
}
r = requests.post(FORUM + "posts", params=QSPARAMS, data=post_details, 
    cookies={"_forum_session": SESSION_COOKIE})
print "Various details of the response from discourse"
print r.text, r.headers, r.status_code
disc_data = json.loads(r.text)
disc_data["FORUM"] = FORUM
print "The link to your new post is: "
print "%(FORUM)st/%(topic_slug)s/%(topic_id)s" % disc_data