Introduction

My son used to be really into the Arkham Horror 2nd Edition board game. If you’ve ever seen this thing, it takes up a lot of space, especially when you have all the expansions, like we do.

One of the biggest space requirements is for the neighbourhood decks. There’s easily a dozen of them.

At the time I was learning Android so I made an app to handle these decks. I wanted it to have all the cards in the app, and I could draw a card with a couple taps.

Eventually I finished it, and I used it for a good many years.

I entertained the idea of making a web-based version, but then backed off of that, because I didn’t like the online requirement.

I did, however, make a complete API that a web-based version would use, and it’s called arkhamdb.

How to use it

First you need a session to store deck states.

If you don’t know which expansions you want, choose all of them with an empty array. Or

curl -X GET \
https://arkhamdb.walberg.ca/expansion | jq

Creating a session

$ curl -X POST \
--header 'Content-Type: application/json' \
--data '{"title": "test game", "expansions": [1, 2, 4]}' \
https://arkhamdb.walberg.ca/session/create

{"sessionid": "5b4e1747-3c2f-43c1-afb2-425ac3a5cf70"}

Drawing a card

$ curl -X POST \
--header 'sessionid: 5b4e1747-3c2f-43c1-afb2-425ac3a5cf70' \
http://127.0.0.1:5000/location/19/draw | jq

{
  "_id": 4,
  "locationid": 19,
  "cardid": 47,
  "description": "You are attacked by a shadowy being, but a large man leaps out of the darkness and drives it off. He introduces himself as <b>Tom \"Mountain\" Murphy</b>. Make a <span class=\"check\">Luck (-2) check</span>, or discard a Whiskey card to pass it automatically. If you pass, he joins your investigation. Take his Ally card if it's available, otherwise he gives you something to protect yourself with. Search the Common Item deck and take the first <b><i>Weapon</i></b> you find. If you fail, nothing happens."
}

Note that card text is formatted as HTML fragments.

There are other endpoints for other decks.

$ flask routes
Endpoint                    Methods  Rule
--------------------------  -------  ------------------------------------
board_get                   GET      /board/<int:board_id>
board_index                 GET      /board
draw_cultencounter_card     POST     /cultencounter/draw
draw_exhibitencounter_card  POST     /exhibitencounter/draw
draw_location_card          POST     /location/<int:location_id>/draw
draw_otherworld_card        POST     /otherworld/<int:otherworld_id>/draw
draw_reckoning_card         POST     /reckoning/draw
expansion_get               GET      /expansion/<int:expansion_id>
expansion_index             GET      /expansion
location_get                GET      /location/<int:location_id>
location_index              GET      /location
otherworld_get              GET      /otherworld/<int:otherworld_id>
otherworld_index            GET      /otherworld
session_create              POST     /session/create

Future plans

Right now it uses SQLite for storage. If I were to get additional users, I would move it to PostgreSQL, since it’s running there anyway. The load is trivial.

OpenAPI Specification

There is an OpenAPI 3.0 specification you can import into a tool like Postman to test the API.