KD:M API

A RESTful API for Monster, by Kingdom Death

Version {{ settings.api.version }} documentation

API Documentation!

The KDM API at https://api.thewatcher.io is a RESTful API for campaign/settlement management in "Monster" by Kingdom Death.

The API is a fan-created and fan-maintained project that is not supported by, affiliated with or otherwise authorized by Kingdom Death.

GitHub | Twitter | Development blog

PUBLIC ROUTES

These routes DO NOT require authentication. Use them to construct dashboard, "create new whatever" type views and to look up game asset data that does not belong to any user.

RouteMethodsComment/Note

User creation and auth: these public routes are how you want to create new users and authenticate existing ones.

/new/user POST, OPTIONS

Include the valid email address and password in the JSON body of your POST to create a new user:

{'username': 'demo@kdm-manager.com', 'password': 'tehH4x0r'}

If you get a 200 back from the API, the user was created without issue. Otherwise, this route produces some pretty explicit feedback when it returns anything other than a 200.

/login POST

The KD:M API uses JSON Web Tokens (https://jwt.io) to manage user sessions and user authentication.

POST to this route with JSON containing user credentials in the body of the request to get a token:

Authorization: {"username": "demo@kdm-manager.com", "password": "l33th4x0r"}

...if your credential checks out, you get a token and the the the user's ID (see below for working with users) back. Easy!

Password reset routes: use these two routes to build a password reset mechanism.
/reset_password/request_code GET

Resetting a password is a two-part process: first, you request a recovery code by posting a registered user's email address to this route. This emails your user with a URL that they can use to reset their PW.

To request a recovery code, simply POST some JSON containting the email of the user:

{'username': 'demo@kdm-manager.com'}

If this comes back 200, then the user has been emailed. Otherwise, if you get a non-200 response, it'll have specific reasons why it did not work.

/reset_password/reset GET

Before you POST to this route, you need a recovery code.

Once you have it, include it with the user's email and new password in the body of your request:

{'username': 'demo@kdm-manager.com', 'password': 's3cr3tP4ss', 'recovery_code': '9FH3BKSNFI37FB476ZHABNDOWHEUSYAB234'}

If your post comes back with a 200, then the user's password has been changed to the password you posted, and you can use it to log them in.

UI/UX Helpers: these routes are intended to help with user experience by rapidly returning basic asset sets.

/get_random_names/<count> GET

Returns count random names for each possible survivor sex.

Important!This method DOES NOT accept POST-type requests and count must be an integer!

Output looks like this:

{
    "M": [
        "Fingal",
        "Pelagius",
        "Stark"
    ],
    "F": [
        "Hope",
        "Moana",
        "Rasha"
    ]
}
/new_settlement GET

This route is deprecated! Use /game_asset/new_settlement instead.

Dashboard: the public endpoints here are meant to be used to create a dashboard or landing page type of view.

/settings.json GET Not strictly a part of the API, but sometimes useful. Hit this route to download an attachement of settings.cfg as JSON.
/settings GET Retrieve settings.cfg as JSON
/world GET Retrieve a JSON representation of aggregate/world stats.

Game asset lookup routes: use these endpoints to get information about game assets, e.g. monsters, gear, etc.

Each of these routes works essentially the same way. You can POST a query to one and retireve data about a single asset if you know its name or handle -OR- you can GET the route to get a list of all assets.

The following lookups are currently supported by the public API:

/campaign GET, POST

This endpoint is deprecated. Use /game_asset/campaign instead.

/expansion GET, POST

This endpoint is deprecated. Use /game_asset/expansion instead.

/game_asset/campaign GET, POST

Accepts a name or handle parameter included in the body of the request (which should be JSON) and returns a JSON representation of a campaign asset:

{"name": "People of the Lantern"}

...gets you back something like this:

{"handle": "people_of_the_lantern","milestones": ["first_child", "first_death", "pop_15", "innovations_5", "game_over" ], "saviors": "1.3.1", "name": "People of the Lantern", "default": true, "principles": ["new_life", "death", "society", "conviction"], "always_available": { "location": ["Lantern Hoard"], "innovation": ["Language"]},"nemesis_monsters": [ "butcher", "kings_man","the_hand","watcher"],"quarries": [ "white_lion","screaming_antelope","phoenix", "beast_of_sorrow", "great_golden_cat", "mad_steed", "golden_eyed_king"],"type": "campaign_definition"}

This also works with handles, e.g.:

{"handle": "people_of_the_stars"}

Like all lookup routes, if you GET this endpoint, the API will return the definitions of all assets.

/game_asset/expansion GET, POST

POST a name or handle to this endpoint to get a particular expansion's asset definition.

For example, if you POST this:

{handle: "gorm"}

You'll get back a nice hunk of JSON definiting the asset:

{
    "ui": {
        "pretty_category": "Quarry"
    },
    "quarries": [
        "gorm"
    ],
    "name": "Gorm",
    "always_available": {
        "location": [
            "Gormery",
            "Gormchymist"
        ],
        "innovation": [
            "Nigredo"
        ]
    },
    "released": {
        "$date": 1457913600000
    },
    "type_pretty": "Expansion",
    "timeline_add": [
        {
            "handle": "gorm_approaching_storm",
            "type": "story_event",
            "ly": 1
        },
        {
            "handle": "gorm_gorm_climate",
            "type": "settlement_event",
            "name": "Gorm Climate",
            "ly": 2
        }
    ],
    "handle": "gorm",
    "type": "expansion",
    "sub_type": "expansion",
    "flair": {
        "color": "EAE40A",
        "bgcolor": "958C83"
    }
}

This route also supports lookups via name values, e.g. {name: "Flower Knight"} or similar.

If you GET this route, it will return the definitions for all supported expansion content as a dictionary/hash.

/game_asset/gear GET, POST

POST a name or handle to this endpoint to do gear lookups:

{handle: "lantern_halberd"}

...gets you back a JSON representation of the asset:

{
    "handle": "lantern_halberd",
    "name": "Lantern Halberd",
    "rules": [
        "Reach 2",
        "Irreplaceable",
        "Unique"
    ],
    "type_pretty": "Gear",
    "keywords": [
        "weapon",
        "melee",
        "two-handed",
        "spear",
        "other"
    ],
    "type": "gear",
    "sub_type": "rare_gear",
    "desc": "After attacking, if standing, you may move up to 2 spaces directly away from the monster."
}

This route also supports name lookups, e.g. {name: "Vespertine Bow"}, etc.

GET this endpoint to dump all gear.

/game_asset/monster GET, POST

Accepts a "name" or "handle" parameter in the POST body and returns a JSON representation of a monster type game asset. For example, POSTing to /monster with JSON such as this:

{"name": "White Lion Lvl. 1"}

...returns JSON like this:

{"comment": "Lvl. 1", "handle": "white_lion", "name": "White Lion", "level": 1, "levels": 3, "sort_order": 0, "type": "quarry"}

Or, with a handle:

{"handle": "manhunter"}

...you get:

{
    "handle": "manhunter",
    "name": "Manhunter",
    "levels": 4,
    "sort_order": 103,
    "type": "nemesis",
    "selectable": false, 
    "misspellings": ["THE MANHUNTER", "MAN HUNTER"],
}

Like all lookup routes, if you GET this endpoint, the API will return the definitions of all assets.

/gear GET, POST

This endpoint is deprecated. Use /game_asset/gear instead.

/monster GET, POST

This endpoint is deprecated. Use /game_asset/monster instead.

PRIVATE ROUTES

Private routes require an Authorization header including a JWT token.

(See the documentation above for more info on how to POST user credentials to the /login route to get a token.)

Generally speaking, when you access any private route, you want your headers to look like this when using private routes:

{ 'content-type': 'application/json', 'Authorization': 'eyJhbGciOiJIUzI1NiIsInR5cCI6...' }

Finally, keep in mind that tokens are extremely short-lived, so you should be prepared to refresh them frequently. See the section below on 'Authorization Token Management' for more info on checking/refreshing tokens.

Important! In order to support the CORS pre-flight checks that most browsers are going to auto-magically perform before POSTing to one of these routes, all private routes supported by the KD:M API also support the OPTIONS method, regardless of how they are documented below.

RouteMethodsComment/Note
Authorization Token Management: once you've got an authorization token, you can work with it using these routes. Most failures from these routes are reported back as 401's, since they concern authorization.
/authorization/check GET,POST,OPTIONS GET or POST to this endpoint to determine if your Authorization header is still valid or if it has expired.
/authorization/refresh POST,OPTIONS

Use the standard 'Authorization' header and POST an empty request to this route to recieve a new Auth token based on the previous one.

On the back end, this route reads the incoming 'Authorization' header and, even if the JWT token is expired, will check the 'login' and 'password' (hash) keys: if they check out, you get a 200 and a brand new token.

Finally, the KDM API does NOT use refresh tokens (it just feels like overkill, you know?).

Administrative views and data: If your user has the 'admin' attribute, you can hit these routes to retrieve data about application usage, etc.
/admin/view/panel GET

API Admin panel. Uses HTTP basic auth (no cookies/no sessions) and requires a user have the 'admin' bit flipped on their user.

/admin/get/user_data GET

Retrieves a nice, juicy hunk of JSON re: recent users of the API.

/admin/get/logs GET

Dumps the contents of a number of system logs from the local filesystem where the API is running and represents them as JSON.

User Routes: all routes for working directly with a user follow a /user/<action>/<settlement_id> convention. These routes are private and require authentication.
/user/dashboard/<user_id> GET, OPTIONS

This fetches a serialized version of the user that includes the /world output as well as a bunch of info about the user, including their friends, settlements they own or are playing in, etc.

Here's a run-down of the key elements:

{
    "is_application_admin": true,
    "meta": {...},
    "user": {...},
    "preferences": [...],
    "dashboard": {
        "campaigns": [...],
        "settlements": [...],
    },
}

The top-level dashboard element includes two arrays: campaigns and settlements.

The campaigns array is a reverse-chronological list of OIDs of all settlements where the user owns a survivor (i.e. the survivor's email attribute matches the users login attribute.

This list can include settlements owned/created by other users: the basic idea behing the campaigns list is that you probably want to show these settlements to the user when they sign in or when they choose which settlement they want to view.

The campaigns array does not include any 'abandoned' settlements (i.e. any settlement with a Boolean True value for the abandoned attribute.

See /settlement/abandon/oid (below) for more on abandoning a settlement.

Conrastively, the settlements array is a chronologically sorted list of all settlement OIDs that belong to the current user, whether abandoned or not.

This is more of an archival/historical sort of list, meant to facilitate that kind of view/list/UX.

/user/get/<user_id> GET, OPTIONS

Retrieve a serialized version of the user who owns <user_id>, to include some additional usage and meta facts about that user.

Like many of the GET routes supported by the KD:M API, this route will return user info whether you use POST or any other supported method.

/user/set/<user_id> POST, OPTIONS

This route supports the assignment of user-specified key/value attributes to the user object.

To set an attribute, include JSON in the body of the request that indicates the key/value to set.

Supported attribute keys include:
keyvalue
current_settlement OID of an existing,non-removed settlement.
Use multiple key/value pairs to set multiple attributes in a single request, e.g. {"current_settlement": $oid, "current_session": $oid}

Important! This route does not support the assignment of arbitrary keys and will completely fail any request that includes unsupported keys!

/user/set_preferences/<user_id> POST, OPTIONS

POST a list of hashes to this endpoint to set user preferences.

Your list has to be named preferences and your hashes have to be key/value pairs where they key is a valid preferences handle and the key is a Boolean:

{preferences: [{handle: "beta", value: true}, {...}]}

Since this is mostly a sysadmin/back-of-house kind of route, it fails pretty easily if you try to POST something it doesn't like. The good news, is that it should fail pretty descriptively.

User Collection Management: The endpoints defined below are used to manage the User's IRL collection of game assets, e.g. Expansions, etc.
/user/add_expansion_to_collection/<user_id> POST, OPTIONS

You can POST a single expansion handle to this endpoint to add it to a user's collection of expansions:

{handle: "manhunter"}
/user/rm_expansion_from_collection/<user_id> POST, OPTIONS

POST some basic JSON to this endpoint to remove an expansion handle from a user's collection:

{handle: "flower_knight"}
Create Assets: To create new assets (user, survivor, settlement), POST JSON containing appropriate params to the /new/<asset_type> route. Invalid or unrecognized params will be ignored!
/new/settlement POST, OPTIONS

Use 'handle' values from the /new_settlement route (see above) as params, like this:

{"campaign": "people_of_the_lantern", "expansions": ["dung_beetle_knight", "lion_god"], "survivors": ["adam", "anna"], "name": "Chicago", "special": ["create_first_story_survivors"]}

If successful, this route returns a serialized version of the new settlement, including its OID, as JSON.

The following special values are supported by the API:

valueresult
create_first_story_survivors Creates two male and two female survivors, assigns them names and places Founding Stones and Cloths in Settlement Storage.
create_seven_swordsmen Creates seven random survivors with the 'Ageless' and Sword Mastery A&Is.

Important! Unsupported special values are ignored.

/new/survivor POST, OPTIONS

This works differently from /new/settlement in a number of significant ways.

In a nutshell, the basic idea here is that the only required key in the JSON you POST to this route is an object ID for the settlement to which the survivor belongs:

{'settlement': '59669ace4af5ca799c968c94'}

Beyond that, you are free to supply any other attributes of the survivor, so long as they comply with the data model for survivors.

Consult the Survivor Data Model (below) for a complete reference on what attributes of the survivor may be set at creation time.

As a general piece of advice, it typically makes more sense to just initialize a new survivor with defaults and then operate on it using the routes below, unless you're doing something inheritance.

For normal inheritance, simply POST the OID's of one or more of the survivor's parents like so:

{settlement: '59669ace4af5ca799c968c94', father: '5a341e6e4af5ca16907c2dff'}

...or like so:

{settlement: '59669ace4af5ca799c968c94', father: '5a341e6e4af5ca16907c2dff', mother: '5a3419c64af5ca11240f519f'}

This will cause normal inheritance rules to be triggered when the new survivor is created.

In order to trigger conditional or special inheritance, e.g. where an innovation requires the user to select a single parent as the donor, you must specify which parent is the donor using the primary_donor_parent key and setting it to 'father' or 'mother':

{settlement: '59669ace4af5ca799c968c94', father: '5a341e6e4af5ca16907c2dff', mother: '5a3419c64af5ca11240f519f', primary_donor_parent: 'father'}

This will cause innovations such as Family to use the primary donor parent to follow one-parent inheritance rules for that innovation.

Important!Just like the /new/settlement route, a successful POST to the /new/survivor route will return a serialized version (i.e. JSON) of the new survivor, complete with the sheet element, etc.

/new/survivors POST, OPTIONS

Not to be confused with /new/survivor (above), this route adds multiple new survivors, rather than just one.

The JSON you have to POST to this route is a little different and more limited than what you would post to /new/survivor.

The following POST key/value pairs are the only ones supported by this route:

keyO/Rvalue typecomment
settlement_id R settlement OID The OID of the settlement to which the new survivors belong.
public O boolean The value of the new survivors' public attribute. Defaults to true.
male O arbitrary int The number of male survivors to create.
female O arbitrary int The number of female survivors to create.
father O survivor OID The OID of the survivor that should be the father of the new survivors.
mother O survivor OID The OID of the survivor that should be the mother of the new survivors.

Creating new survivors this way is very simple. This JSON, for example, would create two new male survivors:

{"male": 2, "settlement_id": "5a1485164af5ca67035bea03"}

A successful POST to this route always returns a list of serialized survivors (i.e. the ones that were created), so if you are creating more than four or five survivors, this route is a.) going to take a couple/few seconds to come back to you and b.) is going to drop a pile of JSON on your head. YHBW.

NB: this route does not support random sex assignment.

Settlement Routes: all routes for working directly with a settlement follow a /settlement/<action>/<settlement_id> convention.

These routes are private and require authentication.

Many operations below require asset handles. Asset handles may be found in the settlement's game_assets element, which contains dictionaries and lists of assets that are available to the settlement based on its campaign, expansions, etc.

Typical settlement JSON looks like this:


            {
                "user_assets": {...},
                "meta": {...},
                "sheet": {...},
                "game_assets": {
                    "milestones_options": {...},
                    "campaign": {...},
                    "weapon_specializations": {...},
                    "locations": {...},
                    "innovations": {...},
                    "principles_options": {...},
                    "causes_of_death": {...},
                    "quarry_options": {...},
                    "nemesis_options": {...},
                    "eligible_parents": {...},
                    ...
                },
            }
            

Important! As indicated elsewhere in this documentation, asset handles will never change. Asset names are subject to change, and, while name-based lookup methods are supported by various routes, using names instead of handles is not recommended.

Settlement data retrieval: The routes in this section only support the GET method and are meant to be used to retrieve certain types of Settlement data.
/settlement/get/<settlement_id> GET

Retrieve a serialized version of the settlement associated with <settlement_id> (to include all related user and game assets, including survivors).

Important! Depending on the number of expansions, survivors, users, etc. involved in a settlement/campaign, this one can take a long time to come back (over 2.5 seconds on Production hardware). YHBW

/settlement/get_game_assets/<settlement_id> GET

Retrieve a serialized version of just the settlement that only includes the settlement's game_assets element.

/settlement/get_sheet/<settlement_id> GET

Retrieve a serialized version of just the settlement that only includes the sheet element.

/settlement/get_summary/<settlement_id> GET

Get a nice, dashboard-friendly summary of a settlement's info.

This route is optimized for speedy returns, e.g. the kind you want when showing a user a list of their settlements.

/settlement/get_campaign/<settlement_id> GET

Retrieve a serialized version of the settlement where the user_assets element includes the groups list, among other things, and is intended to be used in creating 'campaign' type views.

Much like the big get route for settlements, this one can take a while to come back, e.g. two or more seconds for a normal settlement. YHBW.

Auxiliary ettlement 'get' routes: attributes such as Survival Limit, Population and Death Count are more or less automatically tracked by the API, but you can use these routes to modify them directly, if necessary.
/settlement/get_event_log/<settlement_id> GET, POST

GET this end point to retrieve all settlement event log entries (in a giant hunk of JSON) in reverse chronological order, i.e. latest first, oldest last.

For higher LY settlements this can be a really huge list of log lines: if you're a front-end developer, definitely consider loading this one AFTER you have rendered the rest of your view.

If you don't want all log lines, you can POST to this endpoint with one of the following params to limit the scope of the return:

keyvalue typescope
lines arbitrary int Limit the return to the last lines-worth of lines: {lines: 10}. Note that this does not make the query or the return time better or faster for settlements with lots of event log lines.
get_lines_after event log OID Limit the return to event log lines created after an event log OID: {get_lines_after: "5a0370b54af5ca4306829050"}
survivor_id arbitrary survivor's OID Limit the return to event log lines that are tagged with a survivor OID: {survivor_id: "5a0123b54af1ca42945716283"}
/settlement/get_innovation_deck/<settlement_id> GET Retrieve the settlement's current innovation deck (as an array).
/settlement/get_storage/<settlement_id> GET

Hit this route to get representations of the settlement's storage.

What you get back is an array with two dictionaries, one for resources and one for gear:

[
    {
        "storage_type": "resources",
        "total":0,
        "name":"Resource",
        "locations": [
            {
                "bgcolor":"B1FB17", 
                "handle":"basic_resources", 
                "name":"Basic Resources", 
                "collection": [
                    {
                        "handle":"_question_marks",
                        "name":"???",
                        "rules":[],
                        "consumable_keywords": ["fish","consumable","flower"],
                        "type_pretty": "Resources",
                        "keywords": ["organ","hide","bone","consumable"], 
                        "desc":"You have no idea what monster bit this is. Can be used as a bone, organ, or hide!",
                        "type":"resources", 
                        "sub_type":"basic_resources", 
                        "quantity":0,"flippers":false
                    },
                    ...
                ],
                ...
            },
    },
], 

Each dictionary in the main array has an array called locations, which is a list of dictionaries where each dict is a possible location for gear or resources.

Each location is an array of dictionaries representing places where a piece of gear or a resource can live, e.g. "White Lion Resources" or "Basic Gear", etc.

Each location dictionary has an array called collection which is a list of dictionaries where each dictionary is a piece of gear or a resource. The attributes of these dictionaries include the desc, quantity, etc.

Settlement attributes: attributes such as Survival Limit, Population and Death Count are more or less automatically tracked by the API, but you can use these routes to modify them directly, if necessary.
/settlement/set_name/<settlement_id> POST

POST some JSON whose body contains the key 'name' and whatever the new name is going to be as that key's value to change the settlement's name:

{'name': 'The Black Lantern'}

Important! Submitting an empty string will cause the API to default the settlement's name to "UNKNOWN". There are no technical reasons (e.g. limitations) for this, but it breaks the display in most client apps, so null/empty names are forbidden.

/settlement/set_attribute/<settlement_id> POST

POST some basic JSON containing an 'attribute' and a 'value' key where 'attribute' is an integer settlement attrib and 'value' is the new value:

{'attribute': 'survival_limit', 'value': 3}

This route also supports incrementing the population and death_count attributes.

/settlement/update_attribute/<settlement_id> POST

POST some JSON containing an 'attribute' and a 'modifier' key where 'attribute' is an integer settlement attrib and 'mofier' is how much you want to increment it by:

{'attribute': 'death_count', 'modifier': -1}

This route also supports incrementing the survival_limit and death_count routes.

/settlement/update_population/<settlement_id> POST

POST some JSON containing the key 'modifier' whose value is an integer that you want to add to the settlement's population number.

This works basically identically to the update_attribute route, so considering using that route instead.

For example, this JSON would add two to the settlement's population number:

{'modifier': 2}

POST negative numbers to decrease.

Important! Settlement population can never go below zero, so any 'modifier' values that would cause this simply cause the total to become zero.

/settlement/update_survivors/<settlement_id> POST

Use this route to update a specific group of survivors, e.g. Departing survivors.

POST some JSON including the type of survivors to include, the attribute to modify, and the modifier:

{include: 'departing', attribute: 'Insanity', modifier: 1}

Important! This route currently only supports the include value 'departing' and will error/fail/400 on literally anything else.

/settlement/set_inspirational_statue/<settlement_id> POST

Set the settlement's inspirational_statue attrib by POSTing a Fighting Art handle to this route:

{'handle': 'leader'}

This route will actually check out the handle and barf on you if you try to POST an unrecognized FA handle to it. YHBW.

/settlement/set_lantern_research_level/<settlement_id> POST

Set the Settlement's Lantern Research Level with some basic JSON:

{'value': 3}

This route is preferably to a generic attribute setting route becuase it a.) ignores values over 5 and b.) forces the attrib, which is not part of the standard data motel, to exist if it does not.

Definitely use this instead of set_attribute.

Expansion content management: add and remove expansion content. These methods require posting lists of expansion content handles.
/settlement/add_expansions/<settlement_id> POST Add expansions to a settlement by POSTing a list of expansion handles. The body of your post should be a JSON-style list: {'expansions': ['beta_challenge_scenarios','dragon_king']}

Note that this route not only updates the settlement sheet, but also adds/removes timeline events, updates the settlement's available game assets (e.g. items, locations, etc.).

/settlement/rm_expansions/<settlement_id> POST Remove expansions from a settlement by POSTing a list of expansion handles. The body of your post should be a JSON-style list: {'expansions': ['manhunter','gorm','spidicules']}

Note that this route not only updates the settlement sheet, but also adds/removes timeline events, updates the settlement's available game assets (e.g. items, locations, etc.).

Important! We're all adults here, and the KDM API will not stop you from removing expansion handles for expansions that are required by your settlement's campaign. If you want to prevent users from doing this, that's got to be part of your UI/UX considerations.

Monster management: update the settlement's quarries, current quarry, nemesis info, etc.
/settlement/set_current_quarry/<settlement_id> POST

This route sets the settlement's 'current_quarry' attribute, which is the monster that the settlement's Departing Survivors are currently hunting.

POST some simple JSON containing a monster name (do not use handles for this):

{'current_quarry': 'White Lion Lvl 2'}

...or, the monster is unique:

{'current_quarry': 'Watcher'}

Important! You're typically going to want to pull monster names from the settlements' game_assets -> defeated_monsters list (which is a list of monster names created for the settlement based on expansion content, etc.)

/settlement/add_defeated_monster/<settlement_id> POST

POST a 'monster' string to this route to add it to the settlement's list of defeated monsters:

{'monster': 'White Lion (First Story)} or {'monster': 'Flower Knight Lvl 1'}

Important! Watch the strings on this one and try to avoid free text: if the API cannot parse the monster name and match it to a known monster type/name, this will fail.

/settlement/rm_defeated_monster/<settlement_id> POST

POST a 'monster' string to this route to remove it from the settlement's list of defeated monsters, i.e. the sheet.defeated_monsters array/list:

{'monster': 'Manhunter Lvl 4'}

Attempts to remove strings that do NOT exist in the list will not fail (i.e. they will be ignored and fail 'gracefully').

/settlement/add_monster/<settlement_id> POST

Use this route to add quarry or nemesis type monsters to the settlement. POST some JSON containing the handle of the monster to add it:

{'handle': 'flower_knight'}

The API will determine whether the monster is a nemesis or a quarry and add it to the appropriate list. For nemesis monsters, use the /settlement/update_nemesis_levels route (below) to manage the checked/completed levels for that nemesis.

Make sure to check the settlement JSON game_assets.monsters and use the correct handle for the desired monster.

/settlement/rm_monster/<settlement_id> POST

POST some JSON containing a quarry or nemesis type monster handle to remove it from the settlement's list:

{'handle': 'sunstalker'}

The API will determine whether the monster is a quarry or a nemesis. When a nemesis monster is removed, its level detail is also removed.

/settlement/update_nemesis_levels/<settlement_id> POST

Use this method to update the Settlement sheet's nemesis_encounters dictionary, i.e. to indicate that a nemesis encounter has occurred.

A typical dictionary might look like this:

"nemesis_encounters": {"slenderman": [], "butcher": [1,2]}

In this example, the settlement has (somehow) encountered a a level 1 Butcher, but has not yet encountered a Slenderman.

To update the dictionary, POST some JSON that includes the nemesis monster's handle and the levels that are complete.

POST this JSON to reset/undo/remove Butcher encounters:

{"handle": "butcher", "levels": []}

POST this JSON to record an encounter with a level 1 Manhunter:

{"handle": "manhunter", "levels": [1]}
Principles and Milestones: routes for setting/unsetting principles and settlement Milestones.
/settlement/add_milestone/<settlement_id> POST

POST a milestone handle (get it from game_assets to this route to add it to the settlement's list of milestones:

{handle: 'game_over'}

...or...

{handle: 'innovations_5'}

This endpoint will gracefully fail and politely ignore dupes.

/settlement/rm_milestone/<settlement_id> POST

POST a milestone handle (get it from game_assets to this route to remove it from the settlement's list of milestones:

{handle: 'pop_15'}

...or...

{handle: 'first_death'}

This endpoint will gracefully fail and politely ignore attempts to remove handles that are not present.

/settlement/set_principle/<settlement_id> POST

POST some JSON to this route to set or unset a settlement principle. Request the handle of the principle and the election you want to make:


            {
                'principle': 'conviction',
                'election': 'romantic',
            }

This route has a couple of unusual behaviors to note:

  • It requires both keys (i.e. you will get a 400 back if you POST any JSON that does not include both).
  • It will accept a Boolean for 'election', because this is how you 'un-set' a principle.

To un-set a principle, simply post the principle handle and set the 'election' key to 'false':

{'principle': 'new_life', 'election': false}

Important! Adding principles to (or removing them from) a settlement automatically modifies all current survivors, in many cases. Be sure to refresh any survivor info after POSTing JSON to this route!

Timeline controls: use these routes to manage the settlement's timeline. These are probably the most complicated controls in the API, so read the docs carefully!
/settlement/add_timeline_event/<settlement_id> POST

Adding a timeline event to a settlement's timeline requires a fairly specific bit of JSON. To add, for example, a settlement event, you need to post JSON that looks like this:

{'type': 'settlement_event', 'ly': 3, 'handle': 'core_haunted', 'name': 'Haunted', 'user_login': 'dev@kdm-manager.com'}

Event names, types, handles, etc. can be found in the settlement's game_assets -> events (which is a dictionary of settlement and story events).

Adding showdown type events works similarly:

{'type': 'showdown_event', 'name': 'White Lion Lvl 1', 'ly': 4, 'user_login': 'user@whatever.com'}

...or, for a special showdown:

{'type': 'special_showdown', 'name': 'Watcher', 'ly': 20, 'user_login': 'qa@kdm-manager.com'}

Here is a list of accepted event 'type' values:

  • showdown_event
  • special_showdown
  • nemesis_encounter
  • settlement_event
  • story_event
Important! Events without handles may be added, which means that you may absolutely add an event that does not come from the settlement's game_assets -> events. Events with neither a name nor a handle may not be added, however.

/settlement/rm_timeline_event/<settlement_id> POST

Works just like the add_timeline_event method, except in reverse. POST some JSON describing a timeline event that exists on the settlement's timeline to remove it:

{'type': 'settlement_event', 'ly': 3, 'handle': 'core_haunted', 'name': 'Haunted', 'user_login': 'dev@kdm-manager.com'}

Since the add_timeline_event method allows for events without handle attributes (i.e. since it will accept JSON with a name and no handle), events may be removed using only their name and Lantern Year ('ly' ) attribute:

{'type': 'nemesis_encounter', 'name': 'Butcher Lvl 1', 'ly': 4, 'user_login': 'user@whatever.com'}
Locations: manage settlement locations and location levels.
/settlement/add_location/<settlement_id> POST

POST a location handle to this route to add it to the settlement's Locations:

{'handle': 'bone_smith'}
/settlement/rm_location/<settlement_id> POST

This is basically the reverse of add_location and works nearly identically. POST a JSON representation of a Location handle to remove it from the settlement's list:

{'handle': 'barber_surgeon'}
/settlement/set_location_level/<settlement_id> POST

For Locations that have a level (e.g. the People of the Sun's 'Sacred Pool'), you may set the Location's level by posting the handle of the location and the desired level:

{'handle': 'sacred_pool', 'level': 2}
Innovations: manage settlement innovations and innovation levels.
/settlement/add_innovation/<settlement_id> POST

POST an Innovation handle to this route to add it to the settlement's Innovations:

{'handle': 'hovel'}

...or:

{'handle': 'mastery_club'}

Important! As far as the API is concerned, Principles (e.g. 'Graves', 'Survival of the Fittest', etc. are not innovations and you will break the website if you try to add a principle as if it were an innovation.

Use set_principle (below) instead.

/settlement/rm_innovation/<settlement_id> POST

This is basically the reverse of add_innovation and works nearly identically. POST a JSON representation of an Innovation handle to remove it from the settlement's list:

{'handle': 'mastery_club'}
/settlement/set_innovation_level/<settlement_id> POST

For Innovations that have a level (e.g. the Slenderman's 'Dark Water Research'), you may set the Innovation's level by posting the handle of the innovation and the level:

{'handle': 'dark_water_research', 'level': 2}
Other: update the settlement's endeavor token count, lost settlements and other miscellaneous Settlement attributes.
/settlement/update_endeavor_tokens/<settlement_id> POST

Use this route to change a settlement's endeavor token count.

POST some JSON containing the number to modify by:

{"modifier": 2}

The above code would add two to the settlement's current total, whereas the code below would decrement by one:

{"modifier": -1}
/settlement/set_lost_settlements/<settlement_id> POST

Use this route to set a settlement's Lost Settlements total.

POST some JSON containing the new value to set it to:

{"value": 2}

The above code would set the settlement's Lost Settlements total to two; negative numbers will default to zero.

Meta and admin controls: manage settlement meta data, including adding/removing settlement notes, changing the list of settlement admins, etc.
/settlement/abandon/<settlement_id> POST

Hit this route with a POST to mark the settlement as abandoned.

Your POST does not need to contain anything (but it does need to be a POST (GET requests will not abandon the settlement.

An abandoned settlement has a date/time stamp of when it was abandoned as its abandoned attribute.

/settlement/add_admin/<settlement_id> POST

POST the email address of a registered user to add them to the list of settlement administrators:

{login: 'demo@kdm-manager.com'}

Disclaimers:

  • This will fail gracefully if the user's email is in the list (so feel free to spam it).
  • This will fail loudly if the email address does not belong to a registered user: you'll get a 400 and a nasty message back.

/settlement/rm_admin/<settlement_id> POST

This is the reverse of the add_admin route.

Basically, you POST some JSON to the route including the email of the user you want to remove from the settlement admins list:

{login: 'demo@kdm-manager.com'}

Like the add_admin route, this one fails gracefully if you try to remove someone who isn't on the list, etc.

/settlement/add_note/<settlement_id> POST

Since any player in a game is allowed to create settlement notes, the JSON required by this endpoint must include a user's OID.

This endpoint supports the following key/value pairs:

keyR/Ovalue
author_id R The creator's OID as a string.
note R The note as a string. We accept HTML here, so if you want to display this back to your users as HTML, you can do that.
author O The creator's login, e.g. demo@kdm-manager.com, as a string. Best practice is to NOT include this, unless you really know what you're doing.
lantern_year O The Lantern Year the note was created. Defaults to the current LY if not specified.

For example, to add a new note to a settlement, your POST body will, at a minimum, look something like this:

{author_id: "5a26eb1a4af5ca786d1ed548", note: "Nobody expects the Spanish Inquisition!"}

Important! This route returns the OID of the newly-created note:

{"note_oid": {"$oid": "5a2812d94af5ca03ef7db6c6"}}

...which can then be used to remove the note, if necessary (see rm_note below).

/settlement/rm_note/<settlement_id> POST

POST the OID of a settlement note to remove it.

{_id: "5a26eb894af5ca786d1ed558"}

As long as you get a 200 back from this one, the note has been removed. If you get a non-200 status (literally anything other than a 200), something went wrong.

/settlement/set_last_accessed/<settlement_id> POST

This endpoint allows you to set the settlement's last_accessed attribute, which is used in dashboard reporting, etc.

POSTing an empty JSON payload to this will cause the settlement's last_accessed value to be set to now.

Survivor Routes: all routes for working directly with an individual survivor follow a /settlement/<action>/<settlement_id> convention.

Like settlement management routes, these routes are private, require authentication and accept the OPTIONS requests method.

Important! Any POST to any of these routes can also include the optional parameter {"serialize_on_response": true} . Including this param will get you a serialized version of the survivor as part of your response.

Survivor Data Model:

keyR/O  type  descriptionrelated endpoints
emailOstrDefaults to the creator's login.set_email
born_in_lyOintDefaults to current LY.
settlementROIDThis must be set to a valid settlement OID at creation time and may never be changed. See /new/survivor above for more info on creating survivors.
publicOboolDefaults to Boolean false. Submitting anything that evaluates to Boolean true will be treated as such.toggle_boolean
nameOstrset_name
sexOstrAt creation time, this can be set to 'M', 'F' or 'R' (for random). Defaults to 'R' during creation if not specified in the POST body.set_sex
survivalOintupdate_survival set_survival
hunt_xpOint
InsanityOintset_attribute update_attribute
HeadOintset_attribute update_attribute
ArmsOintset_attribute update_attribute
BodyOintset_attribute update_attribute
WaistOintset_attribute update_attribute
LegsOintset_attribute update_attribute
CourageOintset_attribute update_attribute
UnderstandingOintset_attribute update_attribute
affinitiesOdictRather than setting this at creation time, consider using upfate_affinities route after creation to set this, unless you really know what you're doingupdate_affinities set_affinity
departingOboolset_status_flag
bleeding_tokensOintupdate_bleeding_tokens set_bleeding_tokens
max_bleeding_tokensOintDefaults to 5.set_attribute
MovementOintDefaults to 5.set_attribute update_attribute
AccuracyOintset_attribute update_attribute
StrengthOintset_attribute update_attribute
EvasionOintset_attribute update_attribute
LuckOintset_attribute update_attribute
SpeedOintset_attribute update_attribute
attribute_detailOdictset_attribute_detail
Weapon ProficiencyOintset_attribute update_attribute
weapon_proficiency_typeOstrhandleset_weapon_proficiency_type
abilities_and_impairmentsOlistNeeds a list of handles from the settlement's game_assets element, e.g. {'abilities_and_impairments': ['ageless','mastery_sword']} or similar.add_game_asset rm_game_asset
cursed_itemsOlistList of handlesadd_cursed_item rm_cursed_item
disordersOlistList of handlesadd_game_asset, rm_game_asset
favoriteOlistlist of user emails, i.e. users who have favorited the survivoradd_favorite rm_favorite
fighting_artsOlistList of handlesadd_game_asset rm_game_asset
fighting_arts_levelsOlistdictionary where each key is a Fighting Art handle whose value is an array, e.g. {'silk_surgeon': [1,2]}toggle_fighting_arts_level
epithetsOlistlist of handlesadd_game_asset rm_game_asset

Important! There are certain endpoints below that may add additional attributes to a survivor record, e.g. controls_of_death, set_retired, etc.

Attributes such as dead and retired are not part of the baseline data model, i.e. they are not part of the survivor record when it is created. YHBW

GET routes: retrieve various types of survivor data.
/survivor/get/<survivor_id> GET Retrieve a serialized version of the survivor.
/survivor/get_lineage/<survivor_id> GET

Retrieve a dictionary of survivor family info.

This method can take a minute to return, as it does recursion, initializes all surviviors, living and dead, etc. It's probably a good idea to use this one with a loading graphic, etc.

/survivor/get_survival_actions/<survivor_id> GET

Retrieve JSON representing the Survival Actions currently available to the survivor:


    [
        {
            "available": false,
            "sort_order": 0,
            "handle": "dodge",
            "name": "Dodge",
            "type": "survival_action",
            "title_tip": "Impairment 'Broken hip' prevents Wallace from using this ability."
        },
        {
            "available": true,
            "handle": "embolden",
            "name": "Embolden",
            "sort_order": 2,
            "type": "survival_action",
            "title_tip": "Settlement innovation 'Sun Language' unlocks this ability."
        },
        {
            "available": false,
            "handle": "overcharge",
            "name": "Overcharge",
            "sort_order": 5,
            "type": "survival_action",
            "title_tip": "Not unlocked."
        }
    ]

This JSON is updated automatically whenever the the settlement's innovations are update or the survivor's abilities are updated.

Asset management: routes for adding, removing and modifying Survivor Sheet game asset info, e.g. Fighting Arts, Disorders, Abilities & Impairments, etc.

Important! Most of these routes have back-end business logic "baked" into them, so it is highly recommended that you reload/re-get your survivor's JSON after POSTing commands to these routes!

/survivor/add_game_asset/<survivor_id> POST

Use this route to add an asset 'handle' of whatever 'type' to a survivor.

Requires both the 'handle' and 'type' keys:

{'handle': 'blind', 'type': 'abilities_and_impairments'} {'handle': 'crossarm_block', 'type': 'fighting_arts'}

Important! This method enforces many of the incoming asset's attributes, including max, epithet, and so on.

PROTIP: if you want the API to assign a random, eligible asset to the survivor, use the bogus/magic handle "_random" instead of a handle from the settlement's game_assets.

/survivor/rm_game_asset/<survivor_id> POST

The exact inverse of add_game_asset, POSTing to this route requires both 'handle' and 'type' keys and removes a game asset handle from a survivor.

/survivor/set_many_game_assets/<survivor_id> POST

This route allows you to add or remove multiple game assets from a survivor by POSTing a list of handles/types, as if you were doing many add_game_asset or rm_game_asset operations serially.

The JSON you have to POST must include the action you want to take:

{
    "action": "rm",
    "game_assets": [
        {"type": "abilities_and_impairments", "handle": "blind"},
        {"type": "fighting_arts", "handle": "crossarm_block"}
    ]
}

Important! As with set_many_attributes(), the hashes in the game_assets list are pressed in the order you POST them. YHBW.

/survivor/replace_game_assets/<survivor_id> POST

This route accepts a list of handles and a type of game asset and then evalutes the survivor's current handles of that type, removing and adding as necessary in order to bring the survivor's list in sync with the incoming list.

Your JSON should look basically like this:

{
    "type": "abilities_and_impairments",
    "handles": [
        "bitter_frenzy","ageless","analyze"
    ]
}

You're going to want to also include {"serialize_on_response": true} in your POST body on this one, because your survivor is DEFINITELY going to come back way different than he was before you did this.

/survivor/add_cursed_item/<survivor_id> POST

POST a cursed item 'handle' to this route to add that cursed item to the survivor:

{'handle': 'thunder_maul'}

Important! This will automatically apply any A&Is and epithets related to the curse to the survivor.

/survivor/rm_cursed_item/<survivor_id> POST

POST a cursed item 'handle' to this route to remove that cursed item from the survivor:

{'handle': 'husk_of_destiny'}

Important! This will automatically apply remove any epithets A&Is, etc. from the survivor (but will not remove any that are still effective, e.g. because another cursed item also requires them.

/survivor/set_partner/<survivor_id> POST

POST the OID of a survivor to this end point to make that survivor this survivor's partner:

{partner_id: "5a53a2154af5ca67743c6c79"}

To remove the survivor's partner, post the magic value 'UNSET' as the partner_id:

{partner_id: "UNSET"}
/survivor/set_special_attribute/<survivor_id> POST

Use this route to set a survivor special attribute to a Boolean value:

{'handle': 'pots_purified', 'value': false}

A couple of things to note here:

  • The 'handle' will be validated and if you POST a bad/bogus handle, you'll get a 400 (or worse).
  • The 'value' must be a Boolean/truthy/falsy type value. Anything else will get you a 400 (probably a 500, tbh).
  • Once added to a survivor, this attribute is not removed, so it will forever be a Boolean attrib of the survivor (i.e. so feel free to reference it after setting it False, etc.).

/survivor/set_weapon_proficiency_type/<survivor_id> POST

POST some JSON containing a weapon proficiency type handle (from the settlement's game_assets to set it as the survivor's weapon type:

{handle: 'sword'}

To unset/remove weapon proficiency type from a survivor, POST they key unset to this endpoint:

{unset: true}
Sheet Attributes: routes for updating Survivor Sheet attributes
/survivor/set_attribute/<survivor_id> POST

Use this route to set an arbitrary survivor attribute to an arbitrary value. Requires 'attribute' and 'value' keys.

POST some JSON containing the 'attrib' name and the new 'value' like so:

{'attribute': 'Strength', 'value': 3}

The JSON above would set the survivor's Strength to three. The 'value' should always be an integer. Negative numbers are supported:

{'attribute': 'Evasion', 'value': -2}
/survivor/set_many_attributes/<survivor_id> POST

This one works similarly to /survivor/set_attribute/<survivor_id> or /survivor/set_attribute_detail<survivor_id>, except it can update a list of attribute/value pairs and/or a list of attribute/detail/value pairs.

Assuming you want to update the base values as well as the details (i.e. attribute modifiers, in game parlance), the body of your POST should look something like this:

{
    attributes: [
        {attribute: 'Strength', value: 2},
        {attribute: 'survival', value: 5}
    ],
    attribute_details: [
        {'attribute': 'Luck', 'detail': 'tokens', 'value': 2},
        {'attribute': 'Strength', 'detail': 'gear', 'value': -1}
    ],
}

Important! Since the attributes array will be processed as a Python list type object, attributes will be updated synchronously, in the order they are posted.

Important! Failures in this method are not atomic, which means that if one hash causes a failure, the whole request will fail and nothing will be saved!

/survivor/set_attribute_detail/<survivor_id> POST

All survivors have an attribute_detail element in their sheet JSON:

        "attribute_detail": {
            "Strength": {
                "tokens": 0,
                "gear": 0
            },
            "Evasion": {
                "tokens": 0,
                "gear": 0
            },
            "Movement": {
                "tokens": 0,
                "gear": 0
            },
            "Luck": {
                "tokens": 0,
                "gear": 0
            },
            "Speed": {
                "tokens": 0,
                "gear": 0
            },
            "Accuracy": {
                "tokens": 1,
                "gear": 0
            }
        },

This is used to manage attribute info that is NOT the base attribute value (see set_attribute and update_attribute for updating base values).

To update attribute_detail info, POST some JSON that includes an 'attribute', 'detail' and 'value':

{'attribute': 'Luck', 'detail': 'tokens', 'value': 2}

The sample code above would set the survivor's 'Luck' attribute detail for 'tokens' to two.

/survivor/update_attribute/<survivor_id> POST

Supports arbitrary survivor attribute updates. Requires JSON contianing an 'attribute' and a 'modifier'. Adds the value of 'modifier' to the current value of 'attribute'.

Sample JSON to increase strength by two:

{'attribute': 'Strength', 'modifier': 2}

Sample JSON to decrease Insanity by 1:

{'attribute': 'Insanity', 'modifier': -1}
/survivor/update_bleeding_tokens/<survivor_id> POST

Use this to add an integer to the survivor's bleeding token count:

{'modifier': -2}

Important! The API will never set the survivor's bleeding_tokens value lower than zero or higher than the survivor's max_bleeding_tokens. It will return 200's to requests that break these rules.

/survivor/set_bleeding_tokens/<survivor_id> POST

Use this route to set the survivor's bleeding_tokens attribute to an arbitrary integer value.

{'value': 4}

Negative values will be ignored (and you'll get a 200 back).

Important! The API will never set the survivor's bleeding_tokens value lower than zero or higher than the survivor's max_bleeding_tokens. It will return 200's to requests that break these rules.

/survivor/set_name/<survivor_id> POST

POST some JSON containing the survivor's new name like so:

{'name': 'Adam'}

Important! POSTing a blank string as the value of 'name' will result in the survivor's name defaulting to 'Anonymous':

{'name': ''}
/survivor/set_retired/<survivor_id> POST

POST some JSON containing a Boolean value representing whether the survivor is retired or not:

{'retired': true}

The 'retired' value will be duck-typed to a Boolean, so posting anything that evaluates true (e.g. 'checked') will count as a Boolean true, for the intents and purposes of this route.

/survivor/set_sex/<survivor_id> POST

Modify the survivor's sex by POSTing a simple JSON object containing the key 'sex' and a value of either 'M' or 'F'.

{'sex': 'M'}

Important! This is not the same as the survivor's 'effective_sex' attribute, which is mutable. Make sure you're modifying the correct one!

/survivor/set_parent/<survivor_id> POST

Update a survivor's father or mother attributes by posting a role (e.g. 'father' or 'mother') plus a valid survivor OID to this endpoint:

{role: 'father', 'oid': 59d78f014af5ca22ab609db2}
Survival: routes for managing the survivor's Survival value.
/survivor/update_survival/<survivor_id> POST

POST a 'modifier' integer to this route to add that number to the survivor's Survival:

{"modifier": 2}

...or:

{"modifier": -1}

Important! The API will only allow values greater than the settlement's Survival Limit if expansion (or other) content requires the settlement to NOT enforce Survival Limit.

Important! The API will normalize negative numbers to zero automatically.

/survivor/set_survival/<survivor_id> POST

POST a 'value' integer to this route to set that integer as the survivor's Survival value.:

{"value": 6}

Important! The API will only allow values greater than the settlement's Survival Limit if expansion (or other) content requires the settlement to NOT enforce Survival Limit.

Important! The API will normalize negative numbers to zero automatically.

Specialty routes and 'meta' data controllers: these routes allow the management of data beyond the standard Survivor Sheet fields. These routes typically expect detailed/complex JSON, so read carefully!
/survivor/controls_of_death/<survivor_id> POST

This route is the all-purpose route for managing aspects of a survivor's death, including when it happened, how it happened and so on.

Supported key/value info:

keyR/Ovalue
dead R Boolean. Set to 'true' if the survivor is dead.
died_in O Integer. The Lantern Year in which the survivor died.
cause_of_death O String. Can be anything, but check the settlement's assets for some recommended values: game_assets.causes_of_death

Here is some example JSON for marking a survivor dead:


            {
                "dead": true,
                "died_in": 4,
                "cause_of_death": "Hack City",
            }
            

To resurrect a survivor (i.e. undo their death), simply post some JSON with {"dead": false} ,

This will unset other death-related attributes, e.g. 'cause_of_death', 'died_in', etc.

Important! Since dead is the only required key in JSON that gets POSTed to this route, there is some defaulting that goes on if the other values are undefined. Be as explicit as possible with this route.

/survivor/set_constellation/<survivor_id> POST

For survivors with Dragon Traits (i.e. PotStars), use this route to set their 'constellation':

{'constellation': 'Witch'}

Simply POST similar JSON to overwrite/change it:

{'constellation': 'Absolute'}

This one also works to unset/remove it:

{'unset': true}

Here is a list of accepted/supported values for 'constellation':

  • Absolute
  • Gambler
  • Goblin
  • Reaper
  • Rust
  • Sculptor
  • Storm
  • Witch

/survivor/set_affinity/<survivor_id> POST

POST some JSON containing the two required keys, 'color' and 'value' to set a single survivor affinity to a new integer value.

{'color': 'blue', 'value': -2}

The 'value' key must always have an integer value.

/survivor/update_affinities/<survivor_id> POST

Works with the Survivor's affinities dictionary, which contains their permanent, non-token affinities and looks like this by default:

{'red': 0, 'blue': 0, 'green': 0}

POST some JSON containing an optional 'operation' key whose value is 'add' or 'rm' to add or subtract an affinities dictionary called 'aff_dict' to/from the survivor.

Important! The 'operation' key is optional because the default behavior of this method/route is to add the incoming 'aff_dict'.

For example, if you wanted to add a permanent blue affinity to the survivor, you would POST this:

{'aff_dict': {'blue': 1}}

Similarly, if you wanted to add two red affinities and subtract one green affinity, you would POST a JSON object like this one:

{'aff_dict': {'red': 2, 'green': -1}, 'operation': 'add'}

If you wanted to subtract a blue and a green affinity from the survivor, you could POST a JSON object like this one:

{'aff_dict': {'blue': 1, 'green': 1}, 'operation': 'rm'}

Important! The 'operation' key's value must be 'add' or 'rm'. Anything else will get you a 400 response from this route.

/survivor/set_savior_status/<survivor_id> POST

POST some JSON to this route to make a survivor into a savior:

{color: 'red'}

This adds all required A&Is, logs a settlement event, etc.

To change what type of savior you want the survivor to be, POST a different color:

{color: 'blue'}

To remove savior status (all A&Is, etc.), POST the unset key to this route thus: {unset: true}

Flags and toggles: special routes and methods for setting/unsetting 'flag' type aspects of the Settlement Sheet.
/survivor/toggle_boolean/<survivor_id> POST

Use this route to toggle Boolean attributes of the survivor data model, such as 'public'

{'attribute': 'public'}

Important! These attributes are not the same as status flags, which also evaluate Boolean when present on the survivor. See set_status_flag and toggle_status_flag routes below for info on working with status flags.

/survivor/toggle_fighting_arts_level/<survivor_id> POST

The API supports toggling on/off individual levels for Survivor Fighting Arts that have levels (e.g. Silk Surgeon). Use this route to toggle an individual level on or off by POSTing the handle and the level:

{'handle': 'silk_surgeon', 'level': 2}

The API does not enforce sequential leveling (i.e. a Survivor can have level 3 withing having lower levels, e.g. 1 or 2), so don't expect any user-friendliness here.

/survivor/toggle_sotf_reroll/<survivor_id> POST

POST a blank/empty request to this route to toggle the survivor's once per lifetime Survival of the Fittest reroll on or off.

Important! The actual attribute of the survivor's sheet is sotf_reroll:

{"sheet": {"sotf_reroll": true, ...}, "meta": {...}, ...}

But since it is not part of the default data model for survivors, it will sometimes simply be undefined/unset, rather than a.) always present and b.) always a boolean.

/survivor/toggle_status_flag/<survivor_id> POST

Works nearly identically to set_status_flag (see above), except toggles the flag on/off. POST simple JSON containing the target 'flag' to toggle it:

{'flag': 'cannot_use_fighting_arts'}
/survivor/set_status_flag/<survivor_id> POST

This route and its related route toggle_status_flag are used to work with Survivor Sheet 'flags'. The following 'flag' attributes can be set to a boolean value:

  • cannot_spend_survival
  • cannot_use_fighting_arts
  • skip_next_hunt
  • departing

To set a flag (i.e. to True/true), POST some JSON to this route that includes the 'flag' key with the value of the flag you want to set:

{'flag': 'cannot_spend_survival'}

To unset/remove a flag, POST the key/value, plus the key 'unset' with a value of True/true:

{'flag': 'skip_next_hunt', 'unset': True}

Meta and admin controls: manage survivor meta data, including adding/removing survivor notes, avatars, color schemes, etc.

(Includes any attribute of the Survivor Sheet that is NOT part of the in-box/paper tracking assets for the survivor.)

/survivor/add_favorite/<survivor_id> POST

Use this route to POST a user's email address and add the address to the survivor's favorite list, i.e. the list of users who have favorited the Survivor:

{'user_email': 'demo@kdm-manager.com'}

This route gracefully fails on bogus requests, so feel free to spam it (haha--j/k).

/survivor/rm_favorite/<survivor_id> POST

Use this route to POST a user's email address and remove the address from the survivor's favorite list, i.e. the list of users who have favorited the Survivor:

{'user_email': 'test@kdm-manager.com'}

This route gracefully fails on bogus requests and will return a a 200 if asked to remove a user that is not currently in the list.

/survivor/add_note/<survivor_id> POST

Adds a text note to a survivor. The note is returned on the serialized survivor (in survivor.notes).

The POST body requirements are simple:

{'note': 'This is my important note about Ugg-Ugg the maker of the soup.'}

Unlike other routes, this one returns the OID of the note:

{'note_oid': {$oid: '58703a398740d9730c7abeb2'}}
/survivor/rm_note/<survivor_id> POST

POST an existing note OID to this route to remove it:

{'_id': '58703a398740d9730c7abeb2'}
/survivor/set_avatar/<survivor_id> POST

POST a base 64 encoded string to this endpoint to set a new avatar for a survivor:

{survivor_avatar: "JJssaK1234bsakq8123..."}

If you're using JS to convert a file to a base 64 string, consider this sample code, which may be helpful. In the sample, evt is the browser event where the users adds the file:

var reader = new FileReader();
reader.readAsBinaryString(evt.target.files[0]);
reader.onload = function () {
    b64_string = btoa(reader.result);
};

...and b64_string is your final output, i.e. the incoming file as a base 64 encoded string, that you want to POST back to the API.

Important! On a successful post, this route returns a 200 as well as some JSON containing the OID of the new avatar:

{avatar_oid: {$oid: "5a2ae8e34af5ca23a86c7247"}}
/survivor/set_color_scheme/<survivor_id> POST

Serialized settlements have an element called survivor_color_schemes, which is a dictionary of color schemes, including handles.

To change a survivor's color scheme, POST some JSON to this route that includes one of those handles:

{handle: 'vibrant_lantern'}

To unset a survivor's color scheme (i.e. to remove the key/value from the survivor's sheet, simply post the key, unset:

{unset: true}
/survivor/set_email/<survivor_id> POST

POST a registered user's email to this route to set the survivor's email address (which is equivalent to setting the survivor's "owner", but does not change the survivor's created_by attribute.

Your JSON should look like this:

{email: 'demo@kdm-manager.com'}

In order to facilitate form validation, this route will will return a 422 is the email you POST is not associated with a registered user of the API.

Important! If you get a 422 back, your survivor was not updated.

If the update was successful, you get a vanilla 200 back.