NAV
cURL

Introduction

Welcome to the LootLocker Game API Reference Documentation.

We do our best to keep this documentation up to date, but if you find any issues, please reach out to us at hello@lootlocker.io, or swing by our Discord Server and talk to us directly.

Authentication

Player Verification

curl -X POST "https://api.lootlocker.io/game/v1/player/verify" \
  -H "Content-Type: application/json" \
  -d "{\"key\": \"your_game_key\", \"platform\": \"steam\", \"token\": 123857128391}"

If your game uses Player Verification, you need to call this endpoint before you can register a session.

The function of this endpoint is to verify the player with the platform they're currently connecting from. Some platforms require the use of player verification. Please refer to the below table.

A successful response:

{
  "success": true
}
Platform Requires Validation
Steam Optional
PlayStation Network Yes
Roblox Yes
iOS Not supported
Android Not supported
Amazon Luna Not supported
Guest Login Not supported

After verifying the player, you should register a session within 5 minutes, or the token will expire, and you have to verify again.

The token parameter is different depending on which platform it is.

For Steam, you need to see the Auth documentation, under the headline Session Tickets and the Steamworks Web API, for information on how to obtain the token.

For PlayStation Network you need to supply the same auth code as when performing a purchase. An example for obtaining this code can be found in the NPAuth sample provided by Sony.

Roblox Verification

curl -X POST "https://api.lootlocker.io/game/v1/player/verify" \
  -H "Content-Type: application/json" \
  -d "{\"key\": \"your_game_key\", \"platform\": \"roblox\", \"token\": roblox_player_id}"

First response

{
  "success": true,
  "challenge": "z2v5YkOWigKVi3v0B8Z8bJncQs56ZC0N0OuwJsf4"
}

Second / Future Verificaiton Requests

curl -X POST "https://api.lootlocker.io/game/v1/player/verify" \
  -H "Content-Type: application/json" \
  -d "{\"key\": \"your_game_key\", \"platform\": \"roblox\", \"token\": roblox_player_id, \"roblox_user_challenge\": \"sha256_hashed_challenge\"}"

For Roblox the token is the Roblox User ID. When using this platform, we require a challenge to be met by the client. On the first request, LootLocker returns a challenge for the Roblox client to save, and use for future verifications. As you see in the example, there is a field called roblox_user_challenge which is the challenge returned from LootLocker, sha256 hashed with the game api key. This is done by concatenating the two strings, with the challenge first (challenge+game_api_key), and no delimiter between them, then sha256 hashing the new string.

The response to a successful Roblox verification is the same as any other verification.

Authentication Request

Registering a session:

# Session registration example with Steam
curl -X POST "https://api.lootlocker.io/game/v2/session" \
  -H "Content-Type: application/json" \
  -d "{\"game_key\": \"your_game_key\", \"platform\": \"steam\", \"player_identifier\": \"76561198023004363\",  \"game_version\": \"0.10.0.0\", \"development_mode\": \"false\"}"

The game API uses the API key for the initial request which registers a session.

Four parameters are expected in this request, with three additional optional parameters.

A successful response looks like this:

{
  "success": true,
  "session_token": "e6fa44946f077dd9fe67311ab3f188c596df9969",
  "player_id": 3,
  "public_uid": "TSEYDXD8",
  "check_grant_notifications": true,
  "check_deactivation_notifications": false,
  "seen_before": true
}

Required: player_identifier, game_key, game_version and platform.

Optional: mac, session_id and development_mode

player_identifier being the ID of the player on the platform the game is currently running on (steamId, PSN id, etc)

game_key being your API key

game_version being the current version of the game in the format 1.2.3.4 (the 3 and 4 being optional but recommended)

mac (OPTIONAL) being the MAC address of the computer the user is currently playing on. This is used for submitting crash logs later and being able to connect it with a player.

session_id (OPTIONAL) being a randomly generated string to identify this current session.

development_mode (OPTIONAL) is a boolean flag you can set to true when you want to test your unpublished changes of assets, settings etc. See the Admin API documentation for more information.

platform being the name of the platform the user is on, we currently support the following:

Platform Parameter value Reference name
Steam steam 64-bit SteamID
Playstation Network psn Online ID
Roblox roblox Roblox user id
iOS ios Device ID
Android android Device ID
Amazon Luna luna Amazon Luna GUID

session_token is the token you need to make additional calls to LootLocker. To see how to send that along with further requests, see Sending Subsequent Requests.

player_id is the players id in LootLocker. This can be used to integrate with third party tools such as Game Analytics and later generate reports on a per player basis.

public_uid is a unique id for a player in your game, that can be used for searching for the player in the LootLocker Player Manager, or used by players to interact with other players, such as sending friend requests, or requesting UGC created by a specific player.

The check_grant_notifications parameter is for cases where the registration of a session might have triggered asynchronously granting assets the the player. Eg. during DLC migration. If this value is true, you should issue a request for the player asset notification endpoint no earlier than 5 minutes after registering the session.

The check_deactivation_notifications is for letting users know that one of their assets have been deactivated since they last logged in, and can't be used. See Player Asset Deactivation Notifications.

If your game uses constant DLC migrations, you will get ID's back of the DLC's you should check with Steam to see if the player owns them. If you own any of them, issue a call to the Initiate DLC Migration endpoint.

A successful response for a game using XP:

{
  "success": true,
  "session_token": "e6fa44946f077dd9fe67311ab3f188c596df9969",
  "player_id": 3,
  "public_uid": "TSEYDXD8",
  "check_grant_notifications": true,
  "check_deactivation_notifications": false,
  "xp": 5,
  "level": 0,
  "seen_before": true
}

A successful response for a game using soft currency:

{
  "success": true,
  "session_token": "e6fa44946f077dd9fe67311ab3f188c596df9969",
  "player_id": 3,
  "public_uid": "TSEYDXD8",
  "check_grant_notifications": true,
  "check_deactivation_notifications": false,
  "account_balance": 1856,
  "seen_before": true
}

A successful response for a game using constant DLC migrations:

{
  "success": true,
  "session_token": "9178407f966bc58f79acbf96b030eaf43738ab84",
  "player_id": 12,
  "public_uid": "TSEYDXD8",
  "seen_before": true,
  "check_grant_notifications": true,
  "check_deactivation_notifications": true,
  "check_dlcs": [438800, 438801, 438802, 439210],
  "xp": 183188,
  "level": 44,
  "level_thresholds": {
    "current": 352300,
    "current_is_prestige": false,
    "next": 362300,
    "next_is_prestige": true
  },
  "account_balance": 97
}

Guest Login

Register New Guest Session Request

curl -X POST "https://api.lootlocker.io/game/v2/session/guest" \
  -H "Content-Type: application/json" \
  -d "{\"game_key\": \"your_game_key\", \"game_version\": \"0.10.0.0\", \"development_mode\": \"false\"}"

Register Existing Guest Session Request

curl -X POST "https://api.lootlocker.io/game/v2/session/guest" \
  -H "Content-Type: application/json" \
  -d "{\"game_key\": \"your_game_key\", \"player_identifier\": \"ec9b35e6-b184-4f34-b49f-980f86b291e2\", \"game_version\": \"0.10.0.0\", \"development_mode\": \"false\"}"

Guest Login is very similar to the other Authentication methods, except that it does away with the platform property in the request body, makes the player_identifier property optional and will return the player_identifier in the response.

The Guest Login should be used when you do not wish to burden your user with having to create an account on one of the other platforms that LootLocker supports. However, it is important to understand that there is no security for these Guest accounts, and if someone can guess the player_identifier of an existing player, they will be able to play as that player.

When using the Guest login, you should nudge your users to migrate to a persistent platform.

The response from this endpoint is almost identical to the one from the normal Authentication call, with the exception that a player_identifier is also returned, that can be used for subsequent authentication calls, to keep the same guest account active over multiple sessions.

Example Response

{
    "success": true,
    "session_token": "e6fa44946f077dd9fe67311ab3f188c596df9969",
    "player_id": 3,
    "public_uid": "TSEYDXD8",
    "player_identifier": "ec9b35e6-b184-4f34-b49f-980f86b291e2",
    "check_grant_notifications": true,
    "check_deactivation_notifications": false,
    "seen_before": true
  }

White Label Authentication

Authenticating with white label login is similar to other platforms, but do have some differences.

Instead of sending a platform and player identifier we send an email and password instead.

Registering a session:

# Session registration example with Steam
curl -X POST "https://api.lootlocker.io/game/v2/session/white-label" \
  -H "Content-Type: application/json" \
  -d "{\"game_key\": \"your_game_key\", \"email\": \"test@lootlocker.io\", \"password\": \"test123123\", \"game_version\": \"0.10.0.0\", \"development_mode\": \"false\"}"

A successful response looks like this:

{
  "success": true,
  "session_token": "e6fa44946f077dd9fe67311ab3f188c596df9969",
  "player_id": 3,
  "public_uid": "TSEYDXD8",
  "check_grant_notifications": true,
  "check_deactivation_notifications": false,
  "seen_before": true
}

Ending A Session

curl -X DELETE "https://api.lootlocker.io/game/v1/session" \
  -H "x-session-token: your_token_here"

For each API request your game makes, LootLocker tracks how long time the player has been playing for. To make this information more accurate, we have a call to indicate that the session is ending.

This endpoint will terminate the session on the LootLocker servers, and any further requests with this token will be rejected with an 401 Unauthroized error.

Example resoponse

{
  "success": true
}

Sending Subsequent Requests

Sending along a session token in a POST request

curl -X POST "https://api.lootlocker.io/game/v1/some_endpoint_here" \
  -d "other_parameter=other_value" \
  -H "x-session-token: your_token_here"

For brevity this is not mentioned in the rest of the calls in the documentation.

The session token is sent as a HTTP header, with the name x-session-token. If this is not sent with a request, an authentication error will be returned.

White Label Login

All white label login endpoints does not require an active session like other game API endpoints.

Instead they require a domain-key header and an optional is-development header. Before any of these endpoints are enabled, you need to first enable the white label login platform in the LootLocker console.

Sign Up

Create a new user in the white label login system.

Signing up triggers an email to the user asking to verify their account.

Input

Field Description
email Email supplied by the user
password Have to be at least 8 characters long
curl -X POST "https://api.lootlocker.io/white-label-login/sign-up" \
-d "{\"email\": \"test@lootlocker.io\", \"password\": \"some password here\"" \
-H "Content-Type: application/json" \
-H "domain-key: 11aaa11" |
-H "is-development: true"

Example Response

{
  "id": 406,
  "game_id": 2,
  "email": "test@lootlocker.io",
  "created_at": "2021-08-25T08:03:34.612346459Z",
  "updated_at": "2021-08-25T08:03:34.612346459Z",
  "deleted_at": null,
  "validated_at": null
}

Request User Verification

If the initial verification email has expired, the user can request a new verification email using this endpoint.

Will return 204 on success.

Input

Field Description
user_id White label login of the user. This is the ID returned when creating the user or when logging in
curl -X POST "https://api.lootlocker.io/white-label-login/request-verification" \
-d "{\"user_id\": 406" \
-H "Content-Type: application/json" \
-H "domain-key: 11aaa11" |
-H "is-development: true"

Request Reset Password

If the user needs to reset their password they can trigger a reset password email using this endpoint.

Will return 204 on success.

Input

Field Description
user_id White label login of the user. This is the ID returned when creating the user or when logging in
curl -X POST "https://api.lootlocker.io/white-label-login/request-reset-password" \
-d "{\"email\": \"test@lootlocker.io\"" \
-H "Content-Type: application/json" \
-H "domain-key: 11aaa11" |
-H "is-development: true"

Login

Used for verifying users credentials against the white label login system. This endpoint is only required for advanced use cases and most games should not need to implement this.

If you want to start a session in the Game API with White Label Login you should use the Start session call endpoint instead.

Input

Field Description
email Email supplied by the user
password Password supplied by the user
curl -X POST "https://api.lootlocker.io/white-label-login/login" \
-d "{\"email\": \"test@lootlocker.io\", \"password\": \"some password here\"" \
-H "Content-Type: application/json" \
-H "domain-key: 11aaa11" |
-H "is-development: true"

Example Response

{
  "id": 405,
  "game_id": 2,
  "email": "test@lootlocker.io",
  "created_at": "2021-08-24T08:21:07Z",
  "updated_at": "2021-08-24T16:45:12Z",
  "deleted_at": null,
  "validated_at": "2021-08-24T08:21:54Z"
}

Player

Get Player Info

curl -X GET "https://api.lootlocker.io/game/v1/player/info"

This endpoint lets you get general information about the player, such as the XP, Level information and their account balance.

If your game does not have currencies enabled, account_balance will be null.

If your game does not have progression enabled, all other values will be null. level_thresholds will be null instead of an object.

Example response

{
    "success": true,
    "account_balance": 0,
    "xp": 0,
    "level": 0,
    "level_thresholds": {
        "current": 0,
        "current_is_prestige": false,
        "next": 1000,
        "next_is_prestige": true
    }
}

Get Player Name

curl -X GET "https://api.lootlocker.io/game/player/name" \
    -H "LL-Version: 2021-03-01"

This endpoint will return the name the player has set. If no name is set, an empty property will be returned.

Example Response

{
    "name": "Player Name"
}

Set Player Name

curl -X PATCH "https://api.lootlocker.io/game/player/name" \
    -H "LL-Version: 2021-03-01" \
    -H "Content-Type: application/json" \
    -d "{\"name\": \"Player Name\"}"

This endpoint will let the player set a name, and return that name on success.

The max length of a name is 255 characters.

Example Response

{
    "name": "Player Name"
}

Get Inventory List

curl -X GET "https://api.lootlocker.io/game/v1/player/inventory/list"

See the Get Inventory Stream endpoint for explanations of the properties in the response objects.

This call offers a paginated list of the players inventory. There are two URL parameters you can use to affect the offset of asset instances returned. after is the highest instance_id returned from the previous call, and it's used to fetch the next page. count is an optional parameter which is the max number of items returned. It defaults to 50, but can be set as high as 200. Anything above 200 will be ignored and the default value used instead.

When using this endpoint, universal assets are not returned as part of the players inventory, and as such you also need to implement the Get Universal Assets endpoint. If you use the streaming inventory endpoint, this is not necessary as universal assets are returned.

Example response object

{
    "success": true,
    "inventory": [
        {
            "instance_id": 538,
            "variation_id": 45,
            "rental_option_id": null,
            "acquisition_source": "grant_default_loadout",
            "asset": {...},
            "rental": {
                "is_rental": false,
                "time_left": null,
                "duration": null,
                "is_active": null
            }
        }
    ]
}

Get Inventory Stream

curl -X GET "https://api.lootlocker.io/game/v1/player/inventory"

Example response object

{
    "instance_id": 538,
    "variation_id": 45,
    "rental_option_id": null,
    "acquisition_source": "grant_default_loadout",
    "asset": {...},
    "rental": {
        "is_rental": false,
        "time_left": null,
        "duration": null,
        "is_active": null
    }
}

This endpoint will return to you all the assets that the player currently owns, as a streaming response, similar to the assets call. The root object will however contain 2 properties, one being instance_id and the other being asset. The asset will be holding the asset object exactly the same way as any other asset - Referenced as "asset": {...} in the example.

If a player owns multiple of the same asset, it will be there multiple times.

If this endpoint is used instead of the Get Inventory List call, you do not need to implement the Get Universal Assets call as those assets are already returned in this response.

Note the rental object. This contains information regarding rental assets. The is_rental property will let you know if the asset is a rental or not, if it isn't you can safely ignore the other parameters in the object. time_left and duration are denoted in seconds, and active lets you know if the rental has been activated and is thus currently active, or if it is waiting to be activated. Expired rentals are not returned. Beware that the time_left property can be negative if you request the inventory after the instance is expired, but it has not yet been expired by LootLocker.

The acquisition_source property will let you know how a player got to own the current instance of the asset. See the below table for all the different ways players can acquire asset instances.

Source Meaning
grant_default_loadout This was part of the games default loadout when the player got it
grant_universal_asset This was a universal asset that the player used, and thus got an instance of
grant_dlc This was granted by using the dlc migration functionality
reward_event This was rewarded as a reward for getting a medal in an event
reward_trigger This was rewarded by the trigger functionality
reward_level_up This was rewarded because the player levelled up
purchase_package This was part of a package the player purchased
purchase_unit This was a single asset the player purchased
steam_command This was a command sent from steam, creating the asset
rent_unit This is a rented asset
reward_collectable This was rewarded through completing a collectable criteria
grant_loot_box This asset was granted from opening a Loot Box

Get Universal Assets

curl -X GET "https://api.lootlocker.io/game/v1/player/inventory/universal"

You only need to implement this endpoint if you use the List inventory call. If you have implemented the streaming inventory call, you can ignore this.

This call offers a paginated list of the games universal assets. There are two URL parameters you can use to affect the offset of assets returned. after is the highest universal_id returned from the previous call, and it's used to fetch the next page. For the first call you can either set this parameter to 0 or skip it. count is an optional parameter which is the max number of items returned. It defaults to 50, but can be set as high as 200. Anything above 200 will be ignored and the default value used instead.

Example response

{
    "success": true,
    "global_assets": [
        {
            "universal_id": 323,
            "variation_id": null,
            "rental_option_id": null,
            "acquisition_source": "grant_universal_asset",
            "asset": {...},
            "rental": {
                "is_rental": false,
                "time_left": null,
                "duration": null,
                "is_active": null
            }
        }
    ]
}

Get Currency Balance

curl -X GET "https://api.lootlocker.io/game/v1/player/balance"

This endpoint will return the amount of credits the current player have on their account.

Example response

{
    "success": true,
    "balance": 0
}

Submit XP

curl -X POST "https://api.lootlocker.io/game/v1/player/xp" \
 -d "{\"points\": 100}" \
 -H "Content-Type: application/json"

This endpoint will receive xp, and award it to the player. The response will hold information about the players current xp and level.

Example response

{
        "success": true,
        "xp": {
                "previous": 0,
                "current": 50
        },
        "levels": [
                {
                        "level": 0,
                        "xp_threshold": 0
                },
                {
                        "level": 1,
                        "xp_threshold": 100
                },
                {
                        "level": 2,
                        "xp_threshold": 200
                }
        ],
        "check_grant_notifications": false
}

The levels array in the response holds level information about the current level (the first object), and the at least the two next, for displaying progress on the client side. In case of a user skipping all the way from level 0 to level 3, you would see 3 additional levels returned in the response.

Example response where assets have been granted

{
        "success": true,
        "xp": {
                "before": 0,
                "current": 50
        },
        "levels": [
                {
                        "level": 0,
                        "xp_threshold": 0
                },
                {
                        "level": 1,
                        "xp_threshold": 100
                },
                {
                        "level": 2,
                        "xp_threshold": 200
                }
        ],
        "check_grant_notifications": true
}

The check_grant_notifications option means that the player has been granted assets with this score submission. In this case you should issue a request to the Player Asset Notifications call immediately, unlike the Session Registration call where you have to wait.

Example error because the game does not use XP

{
        "success": false,
        "error": "Game does not use XP"
}

Get Other Players XP And Level

curl -X GET "https://api.lootlocker.io/game/v1/player/score/76561198023004363?platform=steam"

Example response

{
        "success": true,
        "xp": 57185,
        "level": 8
}

The platform parameter is optional. If you do not supply one, the backend is gonna default to the same one as the current player is on.

If the player does not exists, you will get a faulty response with the error field set to "Unknown player".

Player Asset Notifications

curl -X GET "https://api.lootlocker.io/game/v1/player/notification/assets"

Example response

{
    "success": true,
    "objects": [
        {
            "instance_id": 5713,
            "variation_id": 28,
            "acquisition_source": "reward_level_up",
            "asset": {
                "id": 16,
                "name": "Founder Gloves",
                "active": true,
                "price": 0,
                "sales_price": null,
                "display_price": "0",
                "shop_thumbnail": "CharacterAttachments/Item Thumbnails/Hands/poppermost/thumb_poppermost-founder.tif",
                "context": "Arms",
                "context_id": 1,
                "detachable": true,
                "updated": "Fri, 20 Feb 2015 21:53:36 +0000",
                "default_variation_id": 28,
                "default_loadouts": {
                    "skier": true,
                    "snowboarder": false
                },
                "unique_instance": false,
                "external_identifiers": {
                    "psn": {
                        "entitlement_id": "CRED01",
                        "service_label": 1
                    }
                },
                "description": "",
                "variations": [
                    {
                        "id": 28,
                        "name": "poppermost-founder",
                        "properties": [
                            {
                                "material_path": "CharacterAttachments/Hands/poppermost/poppermost-founder/poppermost-founder.mtl",
                                "binding_path": "CharacterAttachments/hands/shared-meshes/gloves-a/gloves-a.skin",
                                "bone_id": 12,
                                "bone_overrides": {}
                            }
                        ]
                    }
                ],
                "filters": [
                    {
                        "value": "Poppermost",
                        "name": "Brand",
                        "url": null
                    },
                    {
                        "value": "13/14",
                        "name": "Season",
                        "url": null
                    }
                ],
                "package_contents": null,
                "storage": [
                    {
                        "key": "dog",
                        "value": "yes"
                    }
                ],
                "files": [
                    "https://cdn.lootlocker.io/141/5f230b1e14614.txt"
                ],
                "data_entities": [
                    "Your games custom data for this asset"
                ]
            }
        }
    ]
}

This endpoint can be called to get assets that have been granted (given to) the player since the last time this endpoint was called. The backend will automatically keep track of when it was last called and thus only return valid information. In case no assets has been granted, the array will be empty.

For information on the acquisition_source parameter, see Get Inventory.

Player Asset Deactivation Notifications

curl -X GET "https://api.lootlocker.io/game/v1/player/notification/deactivations"

This endpoint will return deactivations since the last time it's been checked. Do not expect both replacement_asset_id and reason to have values at the same time. They can have, but it is not required.

Example response

{
    "success": true,
    "objects": [
        {
            "deactivated_asset_id": 4,
            "replacement_asset_id": 5,
            "reason": "Here is a good reason for deactivating this asset."
        }
    ]
}

Initiate DLC Migration

curl -X POST "https://api.lootlocker.io/game/v1/player/dlcs"

This endpoint will initiate a DLC migration for the current player. 5 minutes after calling this endpoint you should issue a call to the Player Asset Notifications call, to get the results of the migration, if any.

Example response

{
    "success": true
}

Get DLCs Migrated

curl -X GET "https://api.lootlocker.io/game/v1/player/dlcs"

This endpoint will return a list of DLC's migrated for the player. The DLC identifiers returned will be the ones of the platform the DLC belongs to. The identifier will always be a string, even if the identifier is numeric.

Example response

{
    "success": true,
    "dlcs": [
        "257300",
        "257301",
        "257302",
        "433770"
    ]
}

Set Profile Private

curl -X DELETE "https://api.lootlocker.io/game/v1/player/profile/public"

This endpoint will set the players profile to private. This means that their inventory will not be displayed publicly on Steam and other places.

Example response

{
    "success": true
}

Set Profile Public

curl -X POST "https://api.lootlocker.io/game/v1/player/profile/public"

This endpoint will set the players profile to public. This means that their inventory will be displayed publicly on Steam and other places.

Example response

{
    "success": true
}

Characters

Create Character

curl -X POST "https://api.lootlocker.io/game/v1/player/character" \
    -d "{\"character_type_id\": 1, \"is_default\": true, \"name\": \"Crazy Monday Chimp\"}" \
    -H "Content-Type: application/json"

When creating a character there is only one required field: character_type_id. See List Character Types to get your games Character Types. The other parameters are optional and are the same as for the Update Character call.

Example Response

{
    "success": true,
    "loadouts": [
        {
            "character": {
                "id": 6171,
                "type": "Heavy Vehicle",
                "name": "Crazy Monday Chimp",
                "is_default": true
            },
            "loadout": [
                {
                    "variation_id": 1294,
                    "instance_id": 170657,
                    "mounted_at": "2015-07-24T12:58:08+0000",
                    "asset": {...},
                    "rental": {
                        "is_rental": false,
                        "time_left": null,
                        "duration": null,
                        "is_active": null
                    }
                }
            ]
        }
    ]
}

Update Character

curl -X PUT "https://api.lootlocker.io/game/v1/player/character/6171" \
-d "{\"is_default\": true, \"name\": \"Crazy Monday Chimp\"}"
-H "Content-Type: application/json"

This endpoint lets you set a character as default, and set the name of the character. None of the parameters are required.

Since changing the default status of a character will also change other characters on the player, the response will be identical to that from the Character Loadouts api call.

The only restraint on the name field is that it can be no longer than 255 characters.

List Character Types

curl -X GET "https://api.lootlocker.io/game/v1/player/character/types

Call this endpoint to list the character types configured for your game. If you have any key/value storage associated with your Character Type, it'll be returned here. Otherwise it will be an empty array.

Example Response

{
    "success": true,
    "character_types": [
        {
            "id": 1,
            "is_default": true,
            "name": "Heavy Vehicle",
            "storage": [
                {
                    "key": "custom_data",
                    "value": "value"
                }
            ]
        }
    ]
}

Character Loadouts

curl -X GET "https://api.lootlocker.io/game/v1/player/character/loadout"

This call will return all characters loadouts for a game, and have some additional information on the characters.

Note the rental object. This contains information regarding rental assets. The is_rental property will let you know if the asset is a rental or not, if it isn't you can safely ignore the other parameters in the object. time_left and duration are denoted in seconds, and active lets you know if the rental has been activated and is thus currently active, or if it is waiting to be activated. Expired rentals are not returned. Beware that the time_left property can be negative if you request the inventory after the instance is expired, but it has not yet been expired by LootLocker.

Successful request (truncated for brevity)

{
    "success": true,
    "loadouts": [
        {
            "character": {
                "id": 6171,
                "type": "Heavy Vehicle",
                "name": "Crazy Monday Chimp",
                "is_default": true
            },
            "loadout": [
                {
                    "variation_id": 1294,
                    "instance_id": 170657,
                    "mounted_at": "2015-07-24T12:58:08+0000",
                    "asset": {...},
                    "rental": {
                        "is_rental": false,
                        "time_left": null,
                        "duration": null,
                        "is_active": null
                    }
                }
            ]
        }
    ]
}

Get Other Players Character Loadouts By Platform Identifier

curl -X GET "https://api.lootlocker.io/game/v1/player/character/loadout/76561198023004363?platform=steam"

This call will return all characters loadouts for a game, and have some additional information on the characters.

The response from this endpoint will be identical to the one from the Character Loadouts api call.

Equip Asset to Default Character

curl -X POST "https://api.lootlocker.io/game/v1/player/equip" \
-d "{\"instance_id\": 35}" \
-H "Content-Type: application/json"

Equipping an asset lets the backend know what the current loadout of a player is, which can then be reported back to other players, used for synchronising across multiple platform, be used to create a profile page, or.. You get the picture.

The ID in this URL is the instance_id that will be returned from the inventory and loadout calls.

When equipping an asset, you will get the full list of equipped assets back in the response (see Get current loadout). This should be treated as the universal truth, and the loadout in the game should reflect this.

Equipping a global asset

curl -X POST "https://api.lootlocker.io/game/v1/player/equip" \
-d "{\"asset_id\": 35, \"asset_variation_id\": 66}" \
-H "Content-Type: application/json"

When you want to equip a global asset, it reqiures the asset_id and an asset_variation_id, which will then create an instance that will be returned just like when equipping with an instance_id.

If you are using the global asset equip syntax on an asset that is not global, you will get a response with success set to false, and a suiting error message.

Equip Asset to Character By Id

curl -X POST "https://api.lootlocker.io/game/v1/player/character/12765/equip" \
-d "{\"instance_id\": 35}" \
-H "Content-Type: application/json"

This endpoint allows you to equip an asset to a character by id.

Just like you can equip a global asset to the default character, you can do the same for this endpoint.

You can obtain the character id from the Characters Loadouts call.

curl -X POST "https://api.lootlocker.io/game/v1/player/character/12765/equip" \
-d "{\"asset_id\": 35, \"asset_variation_id\": 66}" \
-H "Content-Type: application/json"

Successful request (truncated for brevity)

{
    "success": true,
    "character": {
        "id": 6171,
        "type": "Heavy Vehicle",
        "name": "Crazy Monday Monkey",
        "is_default": true
    },
    "loadout": [
        {
            "variation_id": 1271,
            "instance_id": 170658,
            "mounted_at": "2015-07-24T12:58:08+0000",
            "asset": {
              "Asset": "information in same format as in the asset calls."
            }
        }
    ]
}

Unequip Asset to Default Character

curl -X DELETE "https://api.lootlocker.io/game/v1/player/equip/1"

Unequipping does the opposite of equipping. For the same reasons. The integer at the end is also the instance_id here.

When un-equipping an asset, you will get the full list of equipped assets back in the response (see Get current loadout). This should be treated as the universal truth, and the loadout in the game should reflect this.

Non successful request because no such instance exists. Status code: 404

{
  "success": false,
  "error": "No such instance"
}

Unequip Asset To Character By Id

curl -X DELETE "https://api.lootlocker.io/game/v1/player/character/6171/equip/170657"

This endpoint lets you unequip assets from a character. The response will return the loadout for this character.

Successful request (truncated for brevity)

{
    "success": true,
    "character": {
        "id": 6171,
        "type": "Heavy Vehicle",
        "name": "Crazy Monday Monkey",
        "is_default": true
    },
    "loadout": [
        {
            "variation_id": 1271,
            "instance_id": 170658,
            "mounted_at": "2015-07-24T12:58:08+0000",
            "asset": {...}
        }
    ]
}

Get Current Loadout to Default Character

curl -X GET "https://api.lootlocker.io/game/v1/player/loadout"

Getting the current loadout will return an array of assets that the user currently have equipped.

A successful response will look similar to this

{
  "success": true,
  "loadout": [
    {
      "variation_id": 2,
      "instance_id": 538,
      "mounted_at": "2014-07-25T11:53:17+0000",
      "asset": {...}
    },
    {
      "variation_id": 9,
      "instance_id": 217,
      "mounted_at": "2014-07-25T11:53:17+0000",
      "asset": {...}
    }
  ]
}

The three fields returned in the call are:

Field name Description
item_id The id of the instance of the asset. This is the unique version of the asset that the player owns
mounted_at The date of equippal in ISO8601 format
asset The asset information needed to represent the asset in-game

Get Other Players Loadout to Default Character

curl -X GET "https://api.lootlocker.io/game/v1/player/loadout/76561198023004363?platform=steam"

This method will return the exact same response as the Get current loadout one, except that it will be for another player.

The platform parameter is optional. If you do not supply one, the backend is gonna default to the same one as the current player is on.

If the player does not exists, you will get a faulty response with the error field set to "Unknown player".

Get Equippable Contexts to Default Character

curl -X GET "https://api.lootlocker.io/game/v1/player/character/contexts"

This endpoint returns the contexts that the players default character can equip. The response format is the same as Getting Contexts, but only includes the equippable contexts for the character.

Get Equippable Contexts by Character ID

curl -X GET "https://api.lootlocker.io/game/v1/player/character/1234/contexts"

This endpoint returns the contexts that the requested player character can equip. The response format is the same as Getting Contexts, but only includes the equippable contexts for the character.

Heroes

In LootLocker, Heroes are an extension of Characters, which can have their own Default Loadouts, and have exceptions (either on an Asset or Context level) to what they can equip.

Get Game Heroes

curl -X GET "https://api.lootlocker.io/game/v1/heroes"

The first thing you will want to do is list the Heroes configured for your game, to get the information needed to create your Hero. This endpoint will list the Heroes with names and character information.

Example Response

{
    "success": true,
    "heroes": [
        {
            "hero_id": 2,
            "character_type_id": 1234,
            "character_type_name": "Heavy",
            "name": "Rick Astley",
            "player_has_hero": false,
            "asset": {...}
        }
    ]
}

List Player Heroes

curl -X GET "https://api.lootlocker.io/game/v1/player/heroes"

This endpoint will return any Heroes the player owns.

The id on the Hero property is the id of the instance of the Hero that the player owns, while the hero_id references the id of the Hero in your game. See how Get Game Heroes does not have an id property, but only a hero_id.

Example Response

{
    "success": true,
    "heroes": [
        {
            "id": 1,
            "hero_id": 2,
            "instance_id": 3,
            "hero_name": "Rick Astley",
            "character_name": "My First Hero",
            "class_name": "Heavy",
            "is_default": true,
            "asset": {...}
        }
    ]
}

The character_name property is the name that can be given to a Hero (and the underlaying Character) by a player. You can safely ignore this if you do not want to use it.

The instance_id references an instance of the asset, that can be used like any other asset instance in LootLocker, for example, to store specific abilities or play time for a specific hero.

List Other Players Heroes by SteamID64

curl -X GET "https://api.lootlocker.io/game/v1/heroes/list/76000000000000000"

This endpoint will return any Heroes the player with the related SteamID64 owns.

The response form this endpoint is identical to listing heroes for the current players own Heroes. See List Player Heroes.

Example Response

{
    "success": true,
    "heroes": [
        {
            "id": 1,
            "hero_id": 2,
            "hero_name": "Rick Astley",
            "character_name": "My First Hero",
            "class_name": "Heavy",
            "is_default": true,
            "asset": {...}
        }
    ]
}

Creating a Hero

curl -X POST "https://api.lootlocker.io/game/v1/player/heroes" \
    -d "{\"hero_id\": 2, \"name\": \"My First Hero\"}"

When creating a player owned hero, you need to supply the id of the game's hero, and can optionally supply a player set name. In the example we've named a "Rick Astley" Hero "My First Hero".

Example Response

{
    "success": true,
    "hero": {
        "id": 1,
        "hero_id": 2,
        "instance_id": 3,
        "hero_name": "Rick Astley",
        "character_name": "My First Hero",
        "class_name": "Heavy",
        "is_default": true,
        "asset": {...}
    }
}

Getting a Hero

curl -X GET "https://api.lootlocker.io/game/v1/player/heroes/1"

Calling this endpoint will return the information about a players hero.

Example Response

{
    "success": true,
    "hero": {
        "id": 1,
        "hero_id": 2,
        "instance_id": 3,
        "hero_name": "Rick Astley",
        "character_name": "My First Hero",
        "class_name": "Heavy",
        "is_default": true,
        "asset": {...}
    }
}

Get Other Players Default Hero By SteamID64

curl -X GET "https://api.lootlocker.io/game/v1/heroes/default/76000000000000000

Use this endpoint to obtain the default hero for another player. This can be used when presenting heroes in a lobby before starting a game session etc.

The response is identical to the one of the Getting a Hero endpoint.

Example Response

{
    "success": true,
    "hero": {
        "id": 1,
        "hero_id": 2,
        "hero_name": "Rick Astley",
        "character_name": "My First Hero",
        "class_name": "Heavy",
        "is_default": true,
        "asset": {...}
    }
}

Updating a Hero

curl -X PUT "https://api.lootlocker.io/game/v1/player/heroes/1"
    -d "{\"name\": \"Renamed Hero\", \"is_default\": false}"

Updating a hero allows you to change the player supplied name of the hero, and setting the default hero for the current player. Setting the default hero to true for one hero will automatically remove it from any other default hero the player might have.

Example Response

{
    "success": true,
    "hero": {
        "id": 1,
        "hero_id": 2,
        "instance_id": 3,
        "hero_name": "Rick Astley",
        "character_name": "Renamed Hero",
        "class_name": "Heavy",
        "is_default": false,
        "asset": {...}
    }
}

Deleting a Hero

curl -X DELETE "https://api.lootlocker.io/game/v1/player/heroes/1"

Deleting a hero will remove it from the players list of heroes. This action is currently unreversible, so you should make sure the player meant to perform the action.

When deleting a hero, the heroes inventory is returned to the player, and their loadout is reset.

Example Response

{"success": true}

Get Hero Inventory

curl -X GET "https://api.lootlocker.io/game/v1/player/heroes/1/inventory"

This endpoint allows you to list asset instances owned by a hero. This is very similar to the player inventory, except that it just returns what is in a heroes inventory.

Note that this endpoint is paginated, and defaults to returning 50 entries. Using the count URL parameter you can set that up to 200.

To retrieve the next page, supply the after URL parameter, with the value of the highest instance_id from your last call.

Example Response

{
    "success": true,
    "inventory": [
        {
            "instance_id": 1,
            "variation_id": 1,
            "rental_option_id": null,
            "acquisition_source": "grant_default_loadout",
            "asset": {...},
            "rental": {
                "is_rental": false,
                "time_left": null,
                "duration": null,
                "is_active": null
            }
        }
    ]
}

Get Hero Loadout

curl -X GET "https://api.lootlocker.io/game/v1/player/heroes/1/loadout"

To list a heros loadout, that is what is currently equipped in the hero, call this endpoint. This same data can also be obtained by getting the character that this hero inherits froms inventory using the Character Loadouts endpoint.

Example Response

{
    "success": true,
    "loadout": [
        {
            "variation_id": 2,
            "instance_id": 538,
            "mounted_at": "2014-07-25T11:53:17+0000",
            "asset": {...},
            "rental": {
                "is_rental": false,
                "time_left": null,
                "duration": null,
                "is_active": null
            }
        }
    ]
}

Get Other Players Hero Loadout

curl -X GET "https://api.lootlocker.io/game/v1/heroes/1/loadout"

When listing another player owned heros loadout, you will need to supply the Hero ID in the URL, in this example 1. This ID can be obtained using the Get Other Players Default Hero By SteamID64 endpoint.

Example Response

{
    "success": true,
    "loadout": [
        {
            "variation_id": 2,
            "instance_id": 538,
            "mounted_at": "2014-07-25T11:53:17+0000",
            "asset": {...},
            "rental": {
                "is_rental": false,
                "time_left": null,
                "duration": null,
                "is_active": null
            }
        }
    ]
}

Add Asset to Hero Loadout

curl -X POST "https://api.lootlocker.io/game/v1/player/heroes/1/loadout"

To equip an asset instance, or a global asset, to a heros loadout, you can call this endpoint. This endpoint works exactly like the Characters Equip endpoints, but lets you do the same operations on a hero directly instead of having to look up the character.

Example Response

{
    "success": true,
    "loadout": [
        {
            "variation_id": 2,
            "instance_id": 538,
            "mounted_at": "2014-07-25T11:53:17+0000",
            "asset": {...},
            "rental": {
                "is_rental": false,
                "time_left": null,
                "duration": null,
                "is_active": null
            }
        }
    ]
}

Remove Asset From Hero Loadout

curl -X DELETE "https://api.lootlocker.io/game/v1/player/heroes/3/loadout/537"

To unequip or remove an asset instance, or a global asset, from a heros loadout, you can call this endpoint. This endpoint works exactly like the Characters Unequip endpoints, but lets you do the same operations on a hero directly instead of having to look up the character.

In the example request, we unequip an asset with the instance_id of 537.

If you have automatic removal of global assets enabled, there will be an extra property on the root of the response, called removed_asset (boolean), letting you know if the asset was removed from the player or not.

Example Response

{
    "success": true,
    "loadout": [
        {
            "variation_id": 2,
            "instance_id": 538,
            "mounted_at": "2014-07-25T11:53:17+0000",
            "asset": {...},
            "rental": {
                "is_rental": false,
                "time_left": null,
                "duration": null,
                "is_active": null
            }
        }
    ]
}

Leaderboards

In the context of the game API leaderboards can be used to view and submit scores for members. To read more about leaderboards in general you can read our Leaderboard Product Documentation.

An entry on a leaderboard is called a member. Since it's possible to have leaderboards for all kinds of cases it doesn't make sense to use players here. Becuase of that member_id can be whatever you want as long as it makes sense in your game. For lots of cases using the players ID will make good sense, but you can imagine a case where you would rank different clans/guilds against eachother for example. In that case you would use clan/guild ID as member_id.

When using a leaderboard ID in any url it's possible to replace this with the key set on the leaderboard instead.

Leaderboard Types

Generic leaderboards

Use this if you want do not want the extended player details from the player type leaderboard. This type allows you to create leaderboards not meant for players (guild/clan for example), or if your player data is not stored in LootLocker.

Player leaderboards

Meant for LootLocker players leaderboards. When submitting scores, you can omit the member_id as the currently authenticated player will always be used by default. When retrieving data LootLocker will automatically attach player data such as name.

Metadata

Sometimes you want to store more data alongside the score for each entry on the leaderboard.

To accomplish this you can enable metadata on the leaderboard at the time of creation.

When submitting scores to that leaderboard you can send the metadata property with a string value in the request and that value will be automatically returned for that score entry.

Get Member Rank

Get rank for single member for a leaderboard.

If leaderboard is of type player a player will also be in the response.

If metadata is enabled for the leaderboard, that will be returned in the response.

curl -X GET "https://api.lootlocker.io/game/leaderboards/1/member/1"

Example Response

{
  "member_id": "1",
  "rank": 3,
  "score": 3004,
  "player": {
    "id": 1,
    "public_uid": "TSEYDXD8",
    "name": "Player Name"
  },
  "metadata": "some metadata"
}

URL Structure

/game/leaderboards/<leaderboard_id|leaderboard_key>/member/<member_id>

URL Parts

Part Description
leaderboard_id ID of the leaderboard
leaderboard_key key of the leaderboard
member_id player_id if player type leaderboard, otherwise id used when submitting the score

Get By List of Members

Get ranks for list of members for a leaderboard. This can be helpful when getting a players friends on leaderboard.

If leaderboard is of type player a player will also be in the response.

If metadata is enabled for the leaderboard, that will be returned in the response.

curl -X POST "https://api.lootlocker.io/game/leaderboards/1/members" \
-d "{\"members\": [\"1\", \"2\"]}" \
-H "Content-Type: application/json"

Example Response

{
  "members": [
    {
      "member_id": "1",
      "rank": 1,
      "score": 10000,
      "player": {
        "id": 1,
        "public_uid": "TSEYDXD8",
        "name": "Player Name"
      },
      "metadata": "some metadata"
    },
    {
      "member_id": "2",
      "rank": 10,
      "score": 5000,
      "player": {...},
      "metadata": "some other metadata"
    }
  ]
}

Get All Member Ranks

curl -X GET "https://api.lootlocker.io/game/leaderboards/member/4?count=1

Get all leaderboards with member information on the ones the member is on, with rank and score, as well as player information if the leaderboard is of type player.

If metadata is enabled for the leaderboard, that will be returned in the response.

Example Response

{
  "leaderboards": [
    {
      "rank": {
        "rank": 1,
        "member_id": "4",
        "score": 134076416,
        "player": {
          "name": "Player Name",
          "id": 4,
          "public_uid": "ABCD1234",
          "metadata": "some metadata"
        }
      },
      "leaderboard_id": 1,
      "leaderboard_key": "LeaderboardKey"
    }
  ],
  "pagination": {
    "total": 100,
    "next_cursor": "2",
    "previous_cursor": null
  }
}

URL Structure

/game/leaderboards/member/<member_id>?count=1&after=0

URL Parts

Part Description
game_id ID of the game
member_id player_id if player type leaderboard, otherwise id used when submitting the score

Query Parameters

Field Description
after Curser for pagination, a cursor will be returned in the response
count Number of members returned per page

Get Score List

curl -X GET "https://api.lootlocker.io/game/leaderboards/1/list?count=10"

Get list of members in rank range. Result is sorted by rank ascending. Maximum allowed members to query for at a time is currently 2000.

If leaderboard is of type player a player will also be in the response.

If metadata is enabled for the leaderboard, that will be returned in the response.

Example Response

{
  "pagination": {
    "total": 10132,
    "next_cursor": 3,
    "previous_cursor": null
  },
  "items": [
    {
      "member_id": "test_id",
      "rank": 1,
      "score": 10000,
      "player": {
        "id": 123,
        "public_uid": "TSEYDXD8",
        "name": "Player Name"
      },
      "metadata": "some metadata"
    },
    {
      "member_id": "test_id2",
      "rank": 2,
      "score": 9999,
      "player": {...},
      "metadata": "some other metadata"
    },
    {
      "member_id": "test_id3",
      "rank": 3,
      "score": 7500,
      "player": {...},
      "metadata": "some third type of metadata"
    }
  ]
}

URL Structure

/game/leaderboards/<leaderboard_id|leaderboard_key>/list?count=10&after=0

URL Parts

Part Description
leaderboard_id ID of the leaderboard
leaderboard_key key of the leaderboard

Query Parameters

Field Description
after Curser for pagination, a cursor will be returned in the response
count Number of members returned per page

Submit Score

curl -X POST "https://api.lootlocker.io/game/leaderboards/1/submit" \
-d "{\"score\": 1000, \"metadata\": \"some metadata\"}" \
-H "Content-Type: application/json"
``

> Example Response

```json
{
  "member_id": "2",
  "rank": 4,
  "score": 1000,
  "metadata": "some metadata"
}

URL Structure

/game/leaderboards/<leaderboard_id|leaderboard_key>/submit

URL Parts

Part Description
leaderboard_id ID of the leaderboard
leaderboard_key key of the leaderboard

Available input fields

All fields are optional.

Field Description
member_id optional player_id if player type leaderboard, otherwise id used when submitting the score
score The score for the entry
metadata If enabled on the leaderboard you can send this. Only accepts a string

Submit scores for member on leaderboard. The member_id in the Game API is automatically filled with the currently authenticated players id.

If metadata is enabled for the leaderboard, that will be returned in the response.

Persistent Player Storage

Get Entire Persistent Storage

curl -X GET "https://api.lootlocker.io/game/v1/player/storage"

The persistent storage lets you save key/value pairs for each player for, syncing settings on different computers or other needs.

This call returns all key/value pairs on record for this player, and can thus be slow if you create many.

Sample success response

{
    "success": true,
    "payload": [
        {
            "key": "user.answer",
            "value": "42",
            "is_public": false
        }
    ]
}

Get a Single Key From Persistent Storage

curl -X GET "https://api.lootlocker.io/game/v1/player/storage?key=user.something"

Very much like the above, except this call only returns one key/value set.

Sample success response

{
    "success": true,
    "payload": {
        "key": "user.answer",
        "value": "42",
        "is_public": false
    }
}

Updating / Creating Key/Value Pairs

curl -X POST "https://api.lootlocker.io/game/v1/player/storage" \
    -d "[{\"key\":\"totalDeaths\",\"value\":\"124\", \"is_public\": true, \"order\":1},{\"key\":\"animal\", \"value\": \"Sheep\", \"order\":2}]"
    -H "Content-Type: application/json"

The response from this request will be that of Get Entire Persistent Storage.

For the key, the following rules apply:

Rule Restriction
Max length 60 characters

For the value, the following rules apply:

Rule Restriction
Max length 260 characters

Note that you can mark a key/value pair as public by including a boolean in the object, named is_public set to true. If you do not want the key/value pair to be public, either send it with the value set to false or omit the key.

For the order you must supply an incrementing integer for each pair. This integer does not have to be continuously increasing, 12, 34, 71 is a perfectly valid sequence.

Deleting a Key/Value Pair

curl -X DELETE "https://api.lootlocker.io/game/v1/player/storage?key=fruit"

When successfully deleting a key/value pair, you will get a response that equals that from Get Entire Persistent Storage. If an error occurs, you will get a 500 Internal Error response, and you should simply try again (for a limited number of times).

Getting Other Players Public Key/Value Pairs

When you need to read another players public key/value storage, you can either use the players id or their public UID.

The response will have the same format as any other player storage API call.

Get by Player ID

curl -X GET "https://api.lootlocker.io/game/v1/player/1234/storage"

Get by Player Public UID

curl -X GET "https://api.lootlocker.io/game/v1/player/A1B2C3D4/storage"

Sample success response

{
    "success": true,
    "payload": [
        {
            "key": "user.answer",
            "value": "42",
            "is_public": true
        }
    ]
}

Asset

Getting Contexts

curl -X GET "https://api.lootlocker.io/game/v1/contexts"

This endpoint will return all the contexts the game has. This includes if a context is locked by an asset or not, for easy handling game side.

Example Response


{
  "success": true,
  "contexts": [
    {
      "id": 3,
      "uuid": "79838f0f-cc37-4854-a81f-eedf7be469b8",
      "name": "Credits",
      "friendly_name": null,
      "detachable": false,
      "user_facing": false,
      "dependent_asset_id": null
    },
    {
      "id": 4,
      "uuid": "4785e978-09f9-4e07-83bd-ed36600930d4",
      "name": "Arms",
      "friendly_name": "Hands",
      "detachable": false,
      "user_facing": true,
      "dependent_asset_id": null
    },
    {
      "id": 5,
      "uuid": "8b860287-5d50-4948-8661-75dbe87b6506",
      "name": "Bindings",
      "friendly_name": null,
      "detachable": false,
      "user_facing": true,
      "dependent_asset_id": null
    },
    {
      "id": 6,
      "uuid": "20914798-d428-4a11-99a1-64ebac1c8d60",
      "name": "Goggles",
      "friendly_name": "Eyes",
      "detachable": true,
      "user_facing": true,
      "dependent_asset_id": null
    }
  ]
}

Getting Asset List

First call

curl -X GET "https://api.lootlocker.io/game/v1/assets/list?count=10&filter=purchasable"

This call is a non-streamed version of the Getting All Assets. It will require multiple calls to LootLocker with a parameter for every call except the first to step forward in the results.

Up to 200 (the default limit is 50 though) assets are returned at a time, and to fetch the next page you have to use the largest ID you've gotten returned in the previous response, in the parameter ?after in the URL. Once you get no assets returned you have gotten them all.

You can set a custom limit, up to 200 items that will be returned, using the query variable count=200. If a non-numeric value is supplied or it's bigger than 200, it will be ignored and a default limit of 50 will be applied.

Next call

curl -X GET "https://api.lootlocker.io/game/v1/assets/list?after=1927&count=10&filter=purchasable

This endpoint also supports filtering assets, using a ?filter URL parameter. Currently the following filters exist:

Filter value Effect
purchasable Only return purchasable assets
!purchasable Only return non-purchasable assets
rentable Only return rentable assets
!rentable Only return non-rentable assets
popular Only return popular assets
!popular Only return non-popular assets

Filters can also be combined by seperating them with a comma. To only get purchasable and popular assets, use the following: purchasable,popular.

If you want to only get assets from a specific context, you can pass along a context_id property with the ID of the context you want to get assets from. Eg. ?after=1927&context_id=192

The objects returned in the array, are the same as returned and documented in the Getting All Assets call. Please reference the text there for detailed information about the properties.

Example Response

{
    "success": true,
    "assets": [
        {
            "id": 1928,
            "uuid": "b85292be-f244-440d-b7ec-d3fbb3775edb",
            "name": "Jester Pro",
            "active": true,
            "purchasable": false,
            "price": 259,
            "sales_price": null,
            "display_price": "259",
            "context": "Bindings",
            "context_id": 2,
            "character_classes": [1,2,3],
            "unlocks_context": null,
            "detachable": false,
            "updated": "Sun, 07 Jan 2018 08:35:34 +0000",
            "marked_new": null,
            "default_variation_id": 2579,
            "default_loadouts": {
                "skier": false,
                "snowboarder": false
            },
            "description": "",
            "links": {
                "thumbnail": "CharacterAttachments/Item Thumbnails/bindings/marker/thumb_marker-14-jesterpro.tif"
            },
            "storage": [
                {
                    "key": "a key",
                    "value": "the value"
                }
            ],
            "rarity": {
                "name": "Legend",
                "short_name": "",
                "color": "BA8BFD"
            },
            "popular": false,
            "popularity_score": 0,
            "package_contents": null,
            "unique_instance": false,
            "external_identifiers": null,
            "rental_options": null,
            "filters": [
                {
                    "value": "Marker",
                    "name": "Brand"
                },
                {
                    "value": "14/15",
                    "name": "Season"
                }
            ],
            "variations": [
                {
                    "id": 2579,
                    "name": "marker-14-jesterpro",
                    "primary_color": "98372B",
                    "secondary_color": "AE2C1C",
                    "links": {
                        "thumbnail": "CharacterAttachments/Item Thumbnails/bindings/marker/thumb_marker-14-jesterpro.tif"
                    },
                    "properties": [
                        {
                            "material_path": "CharacterAttachments/Bindings/Marker/marker-14-jesterpro/marker-14-jesterpro.mtl",
                            "binding_path": "CharacterAttachments/bindings/marker/marker-13-jester18pro/marker-13-jester18pro.cgf",
                            "bone_id": 75,
                            "bone_overrides": {}
                        },
                        {
                            "material_path": "CharacterAttachments/Bindings/Marker/marker-14-jesterpro/marker-14-jesterpro.mtl",
                            "binding_path": "CharacterAttachments/bindings/marker/marker-13-jester18pro/marker-13-jester18pro.cgf",
                            "bone_id": 74,
                            "bone_overrides": {}
                        }
                    ]
                }
            ],
            "featured": false,
            "context_locked": false,
            "initially_purchasable": false,
            "files": [
                {
                    "url": "https://cdn.lootlocker.io/141/5f230b1e14614.txt",
                    "tags": [
                        "never",
                        "gonna",
                        "give",
                        "you",
                        "up"]
                }
            ],
            "data_entities": [
                "Your games custom",
                "data for this asset"
            ],
            "asset_candidate": {
                "created_by_player_id": 1234,
                "created_by_player_uid": "A1B2C3D4"
            },
            "drop_table_max_picks": null
        }
    ]
}

If your game has UGC enabled, you can send a GET style url parameter along to have UGC Assets returned: ?include_ugc=true.

If you only want a subset of the assets your game owns, you can use the filters to include only the ones you want, by adding a GET style parameter to the url like so: ?asset_filters=key1=value1;key2=value2 etc. Any filters supplied need to be present on all assets for them to be returned. A maximum of 5 filters can be applied, any additional filters will be ignored.

Getting Assets By IDs

curl -X GET "https://api.lootlocker.io/game/v1/assets/by/id?asset_ids=1,2,3,4"

This endpoint lets you retrieve only specific Assets by their ID's. The response is identical to the one from Getting Asset List.

Getting All Assets

Get all

curl -X GET "https://api.lootlocker.io/game/v1/assets"

This call is a little special as it will stream you multiple JSON objects, which you will need to be able to handle on your end.

The first JSON object you will receive is a success status.

Get since a date

curl -X GET "https://api.lootlocker.io/game/v1/assets?since=2014-10-15 19:11:53"

After that object you will start receiving the asset objects. See example object to the right. These objects will be valid JSON in their own entities, and they will arrive one at a time. You should parse and handle them as they come in.

The end of the request is marked by JSON object with just one key; streamedObjectCount. This will hold an integer of how many assets were sent. Once this is received you can safely close the connection.

Example of the first object you will receive

{"success":true}

The price and sales_price fields is for displaying a price in the store. If the asset is currently discounted, the sales_price will be set to a non-null value, and you should display that instead of the price field. You can use the difference between the two prices to calculate percentage or discount amount if you wish to do so. display_price is a formatted value sent by the backend, as a string. For virtual currencies it will hold just a number, but for real world currencies it will show the correct price in local currency (Only Play Station currently. Steam will just show the USD price set on the backend). This is useful when listing credits for sale, or if your game does not use virtual currencies.

The type field references types you can arbitrarily set in the management interface. These are to help you differentiate between what different kinds of assets you might have, such as "clothing", "currency", "equipment" etc.

The featured field lets you know if this asset is featured or not. Do with that information what you want. If the asset is an asset for sale, take the player to the store. If it's an event that everyone can participate in, take them to it etc.

The marked_new field lets you annotate your assets with a new badge or similar. This date is in the format RFC-2822, but it can also contain a null value in case it's never been set.

The detachable field lets you know if this is an asset that can be detached, such that the player can choose to not use it in their loadout. If an asset if is a type that does not have a context, the detachable flag will be null.

The context_locked field lets you know if this asset is currently locked because the player does not own the necessary asset to grant access to it's context.

The unlocks_context field is a string with the name of the context that it unlocks. If the asset does not unlock any context, the value will be null.

To handle rental, have a look at rental_options, which specifies the price for rental tiers, a name for each of them and so forth. The duration field is the duration of the rental in seconds.

Under each binding you will see a bone_id, which refers to bones returned from the asset bone call. If there are any deviations from a standard bone, it will be sent along with the binding information. See the example.

You will also see filters if any are defined in the backend. In this example there is one called Brand and one called Season. Do with these what you please.

Under the storage property you will see the keys and values set in the LootLocker Management Console.

The character_classes property contains a list of the ID's of the character classes that can equip this asset.

Example of the asset objects you will receive

{
    "id": 4,
    "uuid": "197261a8-b5be-47ef-874c-830c554595a1",
    "name": "Sven",
    "active": true,
    "price": 0,
    "sales_price": null,
    "display_price": "0",
    "shop_thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif",
    "context": "Arms",
    "context_id": 1,
    "character_classes": [1,2,3],
    "detachable": true,
    "purchasable": true,
    "initially_purchasable": true,
    "updated": "Wed, 04 Feb 2015 15:17:00 +0000",
    "marked_new": "Tue, 20 Oct 2015 21:53:45 +0000",
    "default_variation_id": 3,
    "default_loadouts": {
        "skier": true,
        "snowboarder": false
    },
    "description": "Asset description",
    "featured": false,
    "context_locked": false,
    "unlocks_context": null,
    "rarity": {
      "name": "Legendary",
      "short_name": "L",
      "color": "336699"
    },
    "popular": true,
    "popularity_score": 11618,
    "unique_instance": false,
    "external_identifiers": {
        "psn": {
            "entitlement_id": "CRED01",
            "service_label": 1
        },
        "apple_app_store": {
            "product_id": "CRED01"
        },
        "google_play": {
            "product_id": "CRED01"
        }
    },
    "variations": [
        {
            "id": 3,
            "name": "lo2-gloves-13-sven",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments\/hands\/lo2\/lo2-gloves-13-sven\/lo2-gloves-13-sven.mtl",
                    "binding_path": "CharacterAttachments\/hands\/shared-meshes\/gloves-a\/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": {

                    }
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        },
        {
            "id": 4,
            "name": "lo2-gloves-13-sven_white",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments\/hands\/lo2\/lo2-gloves-13-sven\/lo2-gloves-13-sven_white.mtl",
                    "binding_path": "CharacterAttachments\/hands\/shared-meshes\/gloves-a\/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": {

                    }
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        },
        {
            "id": 5,
            "name": "lo2-gloves-13-sven_green",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments\/hands\/lo2\/lo2-gloves-13-sven\/lo2-gloves-13-sven_green.mtl",
                    "binding_path": "CharacterAttachments\/hands\/shared-meshes\/gloves-a\/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": {

                    }
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        }
    ],
    "filters": [
        {
            "value": "lo2",
            "name": "Brand"
        },
        {
            "value": "13\/14",
            "name": "Season"
        }
    ],
    "rental_options": [
        {
            "id": 1,
            "name": "3 Day Ski Pass",
            "duration": 259200,
            "price": 49,
            "sales_price": null,
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven-rental-3-days.tif"
            }
        }
    ],
    "files": [
        {
            "url": "https://cdn.lootlocker.io/141/5f230b1e14614.txt",
            "tags": [
                "never",
                "gonna",
                "give",
                "you",
                "up"]
        }
    ],
    "data_entities": [
        "Your games custom data for this asset"
    ],
    "asset_candidate": {
        "created_by_player_id": 1234,
        "created_by_player_uid": "A1B2C3D4"
    },
    "drop_table_max_picks": null
}

The end of the request is marked by a small object indicating how many assets were sent

{"streamedObjectCount":7}

Example of the asset object with bone variations

{
    "id": 4,
    "uuid": "197261a8-b5be-47ef-874c-830c554595a1",
    "name": "Sven",
    "active": true,
    "price": 0,
    "sales_price": null,
    "display_price": "0",
    "shop_thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif",
    "context": "Arms",
    "context_id": 1,
    "character_classes": [1,2,3],
    "detachable": true,
    "updated": "Wed, 04 Feb 2015 15:17:00 +0000",
    "marked_new": "Tue, 20 Oct 2015 21:53:45 +0000",
    "default_variation_id": 3,
    "default_loadouts": {
        "skier": true,
        "snowboarder": false
    },
    "description": "",
    "featured": false,
    "rarity": {
      "name": "Legendary",
      "short_name": "L",
      "color": "336699"
    },
    "popular": true,
    "popularity_score": 11618,
    "unique_instance": false,
    "external_identifiers": {
        "psn": {
            "entitlement_id": "CRED01",
            "service_label": 1
        },
        "apple_app_store": {
            "product_id": "CRED01"
        },
        "google_play": {
            "product_id": "CRED01"
        }
    },
    "variations": [
        {
            "id": 3,
            "name": "lo2-gloves-13-sven",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments\/hands\/lo2\/lo2-gloves-13-sven\/lo2-gloves-13-sven.mtl",
                    "binding_path": "CharacterAttachments\/hands\/shared-meshes\/gloves-a\/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": [
                        {
                            "name": "Position",
                            "value": "0,0.24771199,0.8292712"
                        }
                    ]
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        },
        {
            "id": 4,
            "name": "lo2-gloves-13-sven_white",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments\/hands\/lo2\/lo2-gloves-13-sven\/lo2-gloves-13-sven_white.mtl",
                    "binding_path": "CharacterAttachments\/hands\/shared-meshes\/gloves-a\/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": [
                        {
                            "name": "Position",
                            "value": "0,0.24771199,0.8292712"
                        }
                    ]
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        },
        {
            "id": 5,
            "name": "lo2-gloves-13-sven_green",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments\/hands\/lo2\/lo2-gloves-13-sven\/lo2-gloves-13-sven_green.mtl",
                    "binding_path": "CharacterAttachments\/hands\/shared-meshes\/gloves-a\/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": {

                    }
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        }
    ],
    "filters": [
        {
            "value": "lo2",
            "name": "Brand",
        },
        {
            "value": "13\/14",
            "name": "Season",
        }
    ],
    "rental_options": [
        {
            "id": 1,
            "name": "3 Day Ski Pass",
            "duration": 259200,
            "price": 49,
            "sales_price": null,
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven-rental-3-days.tif"
            }
        }
    ],
    "storage": [
        {
            "key": "dog",
            "value": "yes"
        }
    ],
    "files": [
        {
            "url": "https://cdn.lootlocker.io/141/5f230b1e14614.txt",
            "tags": [
                "never",
                "gonna",
                "give",
                "you",
                "up"]
        }
    ],
    "data_entities": [
        "Your games custom data for this asset"
    ],
    "asset_candidate": {
        "created_by_player_id": 1234,
        "created_by_player_uid": "A1B2C3D4"
    },
    "drop_table_max_picks": null
}
{
    "id": 1,
    "name": "Sven",
    "active": true,
    "price": 0,
    "sales_price": null,
    "display_price": "0",
    "shop_thumbnail": "CharacterAttachments/Item Thumbnails/hands/lo2/thumb_lo2-gloves-13-sven.tif",
    "context": "Arms",
    "context_id": 1,
    "character_classes": [1,2,3],
    "detachable": true,
    "updated": "Tue, 13 Jan 2015 14:14:28 +0000",
    "marked_new": "Tue, 20 Oct 2015 21:53:45 +0000",
    "default_variation_id": 1,
    "default_loadouts": {
        "skier": true,
        "snowboarder": false
    },
    "description": "",
    "popularity_score": 11618,
    "unique_instance": false,
    "external_identifiers": {
        "psn": {
            "entitlement_id": "CRED01",
            "service_label": 1
        },
        "apple_app_store": {
            "product_id": "CRED01"
        },
        "google_play": {
            "product_id": "CRED01"
        }
    },
    "variations": [
        {
            "id": 1,
            "name": "lo2-gloves-13-sven",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments/hands/lo2/lo2-gloves-13-sven/lo2-gloves-13-sven.mtl",
                    "binding_path": "CharacterAttachments/hands/shared-meshes/gloves-a/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": [
                        {
                            "name": "Position",
                            "value": "0,0.24771199,0.8292712"
                        }
                    ]
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        },
        {
            "id": 2,
            "name": "lo2-gloves-13-sven_white",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments/hands/lo2/lo2-gloves-13-sven/lo2-gloves-13-sven_white.mtl",
                    "binding_path": "CharacterAttachments/hands/shared-meshes/gloves-a/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": [
                        {
                            "name": "Position",
                            "value": "0,0.24771199,0.8292712"
                        }
                    ]
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        },
        {
            "id": 3,
            "name": "lo2-gloves-13-sven_green",
            "primary_color": "FFFFFF",
            "secondary_color": null,
            "properties": [
                {
                    "material_path": "CharacterAttachments/hands/lo2/lo2-gloves-13-sven/lo2-gloves-13-sven_green.mtl",
                    "binding_path": "CharacterAttachments/hands/shared-meshes/gloves-a/gloves-a.skin",
                    "bone_id": 12,
                    "bone_overrides": {}
                }
            ],
            "links": {
                "thumbnail": "CharacterAttachments\/Item Thumbnails\/hands\/lo2\/thumb_lo2-gloves-13-sven.tif"
            }
        }
    ],
    "filters": [
        {
            "value": "lo2",
            "name": "Brand",
            "url": "url/to/file.tif"
        },
        {
            "value": "13/14",
            "name": "Season",
            "url": null
        }
    ],
    "rental_options": null,
    "storage": [
        {
            "key": "dog",
            "value": "yes"
        }
    ],
    "files": [
        {
            "url": "https://cdn.lootlocker.io/141/5f230b1e14614.txt",
            "tags": [
                "never",
                "gonna",
                "give",
                "you",
                "up"]
        }
    ],
    "data_entities": [
        "Your games custom data for this asset"
    ],
    "asset_candidate": {
        "created_by_player_id": 1234,
        "created_by_player_uid": "A1B2C3D4"
    },
    "drop_table_max_picks": null
}

Getting Asset Bone Information

curl -X GET "https://api.lootlocker.io/game/v1/asset/bones"

This call will return you all the default bones. If a binding overrides anything on a bone, it will be returned along with the binding.

Sample success response

{
    "success": true,
    "bones": [
        {
            "parameters": {
                "Rotation": "1,0,0,0",
                "Position": "-0.16281861,0.007631816,-0.93363667",
                "BoneName": "Bip01 L Foot",
                "Flags": "0",
                "Mass": "1.4",
                "Binding": "CharacterAttachments/bindings/lo2/lo2-bindings-13-pilen/lo2-bindings-13-pilen.cgf"
            },
            "id": "7",
            "name": "bindings_left"
        },
        {
            "parameters": {
                "Rotation": "1,0,0,0",
                "Position": "0.16281861,0.007631816,-0.93363667",
                "BoneName": "Bip01 R Foot",
                "Flags": "0",
                "Mass": "1.4",
                "Binding": "CharacterAttachments/bindings/lo2/lo2-bindings-13-pilen/lo2-bindings-13-pilen.cgf"
            },
            "id": "8",
            "name": "bindings_right"
        },
        {
            "parameters": {
                "Rotation": "0.70006877,0.0077114832,0.0037791394,0.71402371",
                "BoneName": "Bip01 Head",
                "Position": "0,0.24771199,0.8292712",
                "Flags": "0"
            },
            "id": "1",
            "name": "flashlight"
        },
        {
            "parameters": {
                "Rotation": "1,0,0,0",
                "BoneName": "Bip01 Head",
                "Position": "0,0,0",
                "Flags": "0",
                "Mass": "0.1"
            },
            "id": "3",
            "name": "goggles"
        },
        {
            "parameters": {
                "Rotation": "1,0,0,0",
                "BoneName": "Bip01 Head",
                "Position": "0,0,0",
                "Flags": "0"
            },
            "id": "4",
            "name": "gogglestrap"
        },
        {
            "parameters": {
                "Rotation": "1,0,0,0",
                "Position": "0,0,0",
                "BoneName": "Bip01 Head",
                "Flags": "0",
                "Mass": "0.5",
                "Binding": "CharacterAttachments/hats/lo2/lo2-hats-13-bovall/lo2-hats-13-bovall.cgf"
            },
            "id": "2",
            "name": "headwear"
        },
        {
            "parameters": {
                "Rotation": "0.80885416,-0.57089424,0.032788098,0.13696483",
                "Position": "-0.53078705,0.15658157,0.030430784",
                "BoneName": "Bip01 L Hand",
                "Flags": "0",
                "Mass": "0.2",
                "Binding": "CharacterAttachments/poles/lo2/lo2-pole-13-spara/lo2-pole-13-spara.cgf"
            },
            "id": "5",
            "name": "pole_left"
        },
        {
            "parameters": {
                "Rotation": "-0.80885416,0.57089424,0.032788098,0.13696483",
                "Position": "0.53078705,0.15658157,0.030430784",
                "BoneName": "Bip01 R Hand",
                "Flags": "0",
                "Mass": "0.2",
                "Binding": "CharacterAttachments/poles/lo2/lo2-pole-13-spara/lo2-pole-13-spara.cgf"
            },
            "id": "6",
            "name": "pole_right"
        },
        {
            "parameters": {
                "Rotation": "1,0,0,0",
                "Position": "-0.16281861,-0.023641124,-0.93918115",
                "BoneName": "Bip01 L Foot",
                "Flags": "0",
                "Mass": "2.5",
                "Binding": "CharacterAttachments/skis/lo2/lo2-skis-13-Spara/lo2-skis-13-Spara.cgf"
            },
            "id": "9",
            "name": "ski_left"
        },
        {
            "parameters": {
                "Rotation": "1,0,0,0",
                "Position": "0.16281861,-0.023641124,-0.93918115",
                "BoneName": "Bip01 R Foot",
                "Flags": "0",
                "Mass": "2.5",
                "Binding": "CharacterAttachments/skis/lo2/lo2-skis-13-Spara/lo2-skis-13-Spara.cgf"
            },
            "id": "10",
            "name": "ski_right"
        },
        {
            "parameters": {
                "Rotation": "1,0,0,0",
                "Position": "0.0015605614,-0.023641124,-0.93918115",
                "BoneName": "Bip01 L Foot",
                "Flags": "0",
                "Mass": "5",
                "Binding": "CharacterAttachments/Snowboards/snowboard_prototype.cgf"
            },
            "id": "11",
            "name": "snowboard"
        }
    ]
}

Getting Asset Information For One or More Assets

The id can also be a comma separated string for getting multiple assets: 16,17.

curl -X GET "https://api.lootlocker.io/game/v1/asset/16"

This endpoint returns data describing assets for game purposes, and it's a streamed response, just like when you call the Get All Assets endpoint.

Each returned asset has it own success status. It can be true or false, and if it's false, an error explaining what went wrong will also be returned, this object will also hold the ID of the asset you requested.

Sample success response

{
  "success": true
}

{
  "id": 916,
  "uuid": "a91adc11-4a7e-452e-be56-74a36bcfd87e",
  "name": "Sialia",
  "active": true,
  "price": 0,
  "sales_price": null,
  "shop_thumbnail": "",
  "context": "Map",
  "context_id": 3,
  "character_classes": [],
  "detachable": false,
  "updated": "Tue, 16 Jun 2015 08:38:19 +0000",
  "default_variation_id": 0,
  "default_loadouts": {
      "skier": true,
      "snowboarder": false
  },
  "description": "",
  "links": null,
  "storage": [
      {
          "key": "a key",
          "value": "the value"
      }
  ],
  "package_contents": null,
  "featured": false,
  "success": true
}

{
  "id": 917,
  "uuid": "8312744b-6817-41b1-a57e-2183dc10c111",
  "name": "Spawn_Event_ShrineTT6",
  "active": true,
  "price": 0,
  "sales_price": null,
  "shop_thumbnail": "",
  "context": "Spawn Point",
  "context_id": 4,
  "character_classes": [],
  "detachable": false,
  "updated": "Mon, 15 Jun 2015 16:19:05 +0000",
  "default_variation_id": 0,
  "default_loadouts": {
      "skier": true,
      "snowboarder": false
  },
  "description": "",
  "links": null,
  "storage": [
      {
          "key": "a key",
          "value": "the value"
      }
  ],
  "files": [
    {
        "url": "https://cdn.lootlocker.io/141/5f230b1e14614.txt",
        "tags": [
            "never",
            "gonna",
            "give",
            "you",
            "up"]
    }
  ],
  "package_contents": null,
  "featured": false,
  "data_entities": [
      "Your games custom data for this asset"
  ],
  "success": true
}

Sample failed request

{
    "success": true
}

{
    "success": false,
    "error": "No such asset",
    "asset_id": 916
}

{
    "id": 917,
    "uuid": "8312744b-6817-41b1-a57e-2183dc10c111",
    "name": "Spawn_Event_ShrineTT6",
    "active": true,
    "price": 0,
    "sales_price": null,
    "shop_thumbnail": "",
    "context": "Spawn Point",
    "context_id": 4,
    "character_classes": [],
    "detachable": false,
    "updated": "Mon, 15 Jun 2015 16:19:05 +0000",
    "default_variation_id": 0,
    "default_loadouts": {
        "skier": true,
        "snowboarder": false
    },
    "description": "",
    "links": null,
    "storage": [
        {
          "key": "a key",
          "value": "the value"
        }
    ],
    "files": [
        {
            "url": "https://cdn.lootlocker.io/141/5f230b1e14614.txt",
            "tags": [
                "never",
                "gonna",
                "give",
                "you",
                "up"]
        }
    ],
    "data_entities": [
        "Your games custom data for this asset"
    ],
    "package_contents": null,
    "featured": false,
    "success": true
}

Listing Favourite Assets

curl -X GET "https://api.lootlocker.io/game/v1/asset/favourites"

This call will simply list the current players favourite assets.

Example response

{
    "success": true,
    "favourites": [
        1,2,3,4,5
    ]
}

Adding Favourite Assets

curl -X POST "https://api.lootlocker.io/game/v1/asset/258/favourite"

This will favourite the asset id that is placed in the url between asset and favourite. The response will be the same as from Listing Favourite Assets.

Removing Favourite Assets

curl -X DELETE "https://api.lootlocker.io/game/v1/asset/258/favourite"

This will remove the asset id that is placed in the url between asset and favourite from the favourite list. The response will be the same as from Listing Favourite Assets.

Asset Instances

Asset instances is what you will be working with when you have a player owned asset. A few actions can be taken on these instances, such as using the key/value storage to track distance traveled or deaths (etc) with one specific asset instance (also referred to as an item).

To call these endpoints, you will need to know the id of the instance you wish to interact with. You will find the instances you will have access to by calling the Get Inventory endpoint.

Getting All Key Value Pairs

curl -X GET "https://f2p.poppemrost.se/game/v1/asset/instance/storage"

This endpoint will return a streamed response with individual objects for each key/value pair.

Example Response

{
    "success": true,
}{
    "instance_id": 1234,
    "storage": {
        "id": 123,
        "key": "fruit",
        "value": "banana"
    }
}{
    "streamedObjectCount": 1
}

Getting All Key Value Pairs to an Instance

curl -X GET "https://api.lootlocker.io/game/v1/asset/instance/57613/storage"

When getting all key value pairs to an instance, you will receive an object with a success property. If this property holds a true value, you will also find a storage property, which will hold an array of key value pairs. In case of an error, the success property will hold a false value, and there will be an error property holding a string explaining what went wrong.

Example Response

{
    "success": true,
    "storage": [
        {
            "id": 1,
            "key": "distanceTraveled",
            "value": "118581"
        },
        {
            "id": 2,
            "key": "deaths",
            "value": "19"
        }
    ]
}

Getting A Key Value Pair By Id

curl -X GET "https://api.lootlocker.io/game/v1/asset/instance/57613/storage/1"

You can get a single key value pair by it's id by tacking the id of a pair on the url you used to get all key value pairs for an instance.

Example Response

{
    "success": true,
    "storage": [
        {
            "id": 1,
            "key": "distanceTraveled",
            "value": "45678"
        }
    ]
}

Creating A Key Value Pair

curl -X POST "https://api.lootlocker.io/game/v1/asset/instance/57613/storage"
  -H "Content-Type: application/json"
  -d "{\"key\": \"distanceTraveled\", \"value\": \"1233\"}"

Creating a key value pair is done by sending a POST request to the same endpoint as you get the list from. There is currently no support for bulk creation of keys. You will have to send multiple requests.

Example Response

{
    "success": true,
    "storage": [
        {
            "id": 1,
            "key": "distanceTraveled",
            "value": "1233"
        }
    ]
}

Updating One Or More Key Value Pairs

curl -X PUT "https://api.lootlocker.io/game/v1/asset/instance/57613/storage"
  -H "Content-Type: application/json"
  -d "{\"storage\": [{\"key\": \"distanceTraveled\", \"value\": \"45678\"}]}"

When you want to update the value of one or more keys, you can simply send a PUT request to the same endpoint as you would for creating a key value pair. The biggest difference is that this endpoint supports bulk requests, meaning the data format is a bit different in that it requires a main property (storage), which is an array holding objects of key value pairs.

Example Response

{
    "success": true,
    "storage": [
        {
            "id": 1,
            "key": "distanceTraveled",
            "value": "1233"
        }
    ]
}

Updating A Key Value Pair By Id

curl -X PUT "https://api.lootlocker.io/game/v1/asset/instance/57613/storage/1"
  -H "Content-Type: application/json"
  -d "{\"key\": \"distanceTraveled\", \"value\": \"45678\"}"

When updating by id, both key and value are optional, but you must supply at least one of them. When updating by id, you can change the key, and keep the value if you wish. The response from this call will only return the affected key value pair.

Example Response

{
    "success": true,
    "storage": [
        {
            "id": 1,
            "key": "distanceTraveled",
            "value": "45678"
        }
    ]
}

Delete A Key Value Pair

curl -X DELETE "https://api.lootlocker.io/game/v1/asset/instance/57613/storage/1"

Deleting a key value pair is done by sending a DELETE request with the id of the pair you want to delete. The response will be the same as calling Getting All Key Value Pairs To An Instance.

Example response

{
    "success": true,
    "storage": [
        {
            "id": 2,
            "key": "deaths",
            "value": "19"
        }
    ]
}

Inspect a Loot Box

curl -X GET "https://api.lootlocker.io/game/v1/asset/instance/57613/inspect"

Asset instances with the type set to loot box can be inspected, to see what assets the player might possibly get when opening them.

You are supplied with the weight of the assets in this call. You can use that to display the chance that a player will get an asset, or to simulate it in a carousel. Sum the weights to know the total lots, and then you have a weight in sum(weights) chance of getting a specific asset. For more information see the article by Peter Kelly on weighted random selection.

Example response

{
    "success": true,
    "contents": [
        {
            "asset_id": 4,
            "asset_variation_id": null,
            "asset_rental_option_id": 11,
            "weight": 200
        },
        {
            "asset_id": 7,
            "asset_variation_id": 5,
            "asset_rental_option_id": null,
            "weight": 2
        },
        {
            "asset_id": 7,
            "asset_variation_id": null,
            "asset_rental_option_id": null,
            "weight": 40
        }
    ]
}

Open a Loot Box

curl -X PUT "https://api.lootlocker.io/game/v1/asset/instance/57613/open"

Asset instances with the type set to loot box can be opened, using this endpoint. Once you call this endpoint, the Loot Box will be removed from the players inventory, and a new asset will be added to the inventory, with the acquisition_source set to grant_loot_box. You will be asked to check the grant notifications to see which asset was granted.

Example response

{
    "success": true,
    "check_grant_notifications": true
}

In a 10000 iteration test we ran, we got the following results:

Asset Weight Times recieved Predicted chance Actual chance
1 1 59 0.55% 0.59%
2 80 4417 44.20% 44.17%
3 100 5524 55.25% 55.24%
Sums 181 10000 100% 100%

For more information see the article by Peter Kelly on weighted random selection.

User Generated Content

With User Generated Content (UGC) your game client can upload Asset Candidates to LootLocker which can be turned into Assets to get the full power of LootLocker's Asset functionality.

Asset Candidates are promoted to Assets once they are marked as complete and have passed moderation. Moderation can be disabled if you do not distribute UGC widely, in which case Asset Candidates will be promoted to Assets upon being marked as complete.

Creating an Asset Candidate

curl -X POST "https://api.lootlocker.io/game/v1/player/assets/candidates" \
    -H "Content-Type: application/json"
    -d "{\"data\": {\"name\": \"My UGC Asset\"}}"

The data property in payload sent when creating an Asset Candidate currently supports the following data, all being optional, but some required for promotion to an Asset.

Property Type Value Required For Promotion
name string A name for the Asset Yes
context_id integer A context_id that will be used when promoting the Asset Candidate to an Asset. Automatically filled if not provided Yes
kv_storage array An array or objects with key and value keys No
filters array An array or objects with key and value keys No
data_entities array An array or objects with name and data keys No

Example Payload

{
    "data": {
        "name": "My UGC Asset",
        "context_id": 1740,
        "kv_storage": [
            {
                "key": "kind",
                "value": "sofa"
            }
        ],
        "filters": [
            {
                "key": "size",
                "value": "large"
            }
        ],
        "data_entities": [
            {
                "name": "astley-paradox",
                "data": "SWYgeW91IGFzayBSaWNrIEFzdGxleSBmb3IgYSBEVkQgb2YgdGhlIG1vdmllIFVwLCBoZSB3b24ndCBnaXZlIGl0IHRvIHlvdSBiZWNhdXNlIGhlJ3MgbmV2ZXIgZ29ubmEgZ2l2ZSB5b3UgVXAuIEhvd2V2ZXIsIGJ5IG5vdCBnaXZpbmcgeW91IFVwIGxpa2UgeW91IGFza2VkIGZvciBpdCwgaGUncyBsZXR0aW5nIHlvdSBkb3duLiBUaGlzIGlzIGtub3duIGFzIHRoZSBBc3RsZXkgcGFyYWRveA=="
            }
        ]
    }
}

The context_id in the above table will be set automatically by LootLocker if you provide none. We suggest you use the context functionality to organize your Asset Candidates if that makes sense in the context of your game.

Example Response

{
    "success": true,
    "asset_candidate_id": 15,
    "asset_candidate": {
        "id": 15,
        "asset_id": null,
        "status": "INCOMPLETE",
        "review_feedback": null,
        "data": {
            "name": "My UGC Asset",
            "kv_storage": [
                {
                    "key": "kind",
                    "value": "sofa"
                }
            ],
            "filters": [
                {
                    "key": "size",
                    "value": "large"
                }
            ],
            "data_entities": [
                {
                    "name": "astley-paradox",
                    "data": "SWYgeW91IGFzayBSaWNrIEFzdGxleSBmb3IgYSBEVkQgb2YgdGhlIG1vdmllIFVwLCBoZSB3b24ndCBnaXZlIGl0IHRvIHlvdSBiZWNhdXNlIGhlJ3MgbmV2ZXIgZ29ubmEgZ2l2ZSB5b3UgVXAuIEhvd2V2ZXIsIGJ5IG5vdCBnaXZpbmcgeW91IFVwIGxpa2UgeW91IGFza2VkIGZvciBpdCwgaGUncyBsZXR0aW5nIHlvdSBkb3duLiBUaGlzIGlzIGtub3duIGFzIHRoZSBBc3RsZXkgcGFyYWRveA=="
                }
            ],
            "context_id": 1740
        },
        "files": [],
        "created_at": "Tue, 17 Nov 2020 12:56:58 +0000",
        "updated_at": "Tue, 17 Nov 2020 12:56:58 +0000"
    }
}

Updating an Asset Candidate

curl -X PUT "https://api.lootlocker.io/game/v1/player/assets/candidates/1234" \
    -H "Content-Type: application/json"
    -d "{\"completed\": true, \"data\": {\"name\": \"My Renamed Asset Candidate\"}}"

When updating an Asset Candidate, you can update all data that you can also set when creating one. Additionally you use this call to mark the Asset Candidate as completed, by sending a property called completed with the value set to boolean true.

Any data property sent along will replace the entirety of that property on the Asset Candidate, so make sure that you send everything you want to store, and not just what's changed.

Example Response

{
    "success": true,
    "asset_candidate": {
        "id": 15,
        "asset_id": 6763,
        "status": "APPROVED",
        "review_feedback": null,
        "data": {
            "name": "My UGC Asset",
            "kv_storage": [
                {
                    "key": "kv-test",
                    "value": "great success"
                }
            ],
            "filters": [
                {
                    "key": "filter-test",
                    "value": "great success"
                }
            ],
            "data_entities": [
                {
                    "name": "Entity test",
                    "data": "flergen dergen hergen"
                }
            ],
            "context_id": 1740
        },
        "files": [],
        "created_at": "Tue, 17 Nov 2020 12:56:58 +0000",
        "updated_at": "Tue, 17 Nov 2020 12:58:25 +0000"
    }
}

Once an Asset Candidate has been marked as completed, it will enter the moderation queue or be directly promoted to an Asset if moderation is disabled for your game. Once this has happened you can no longer update it.

Deleting an Asset Candidate

curl -X DELETE "https://api.lootlocker.io/game/v1/player/assets/candidates/1234"

Deleting Asset Candidates can be done by ID, and only while the Asset Candidate haven't yet been promoted to an Asset.

Example Response

{"success": true}

Listing Asset Candidates

curl -X GET "https://api.lootlocker.io/game/v1/player/assets/candidates"

You can retrieve all Asset Candidates belonging to the current player, by issuing a call to this endpoint. If an Asset Candidate have been promoted to an Asset, the Asset's ID will be set in the property asset_id.

Example Response

{
    "success": true,
    "asset_candidates": [
        {
            "id": 3876,
            "asset_id": 6737,
            "status": "APPROVED",
            "review_feedback": null,
            "data": {
                "name": "My UGC Asset",
                "kv_storage": [
                    {
                        "key": "kind",
                        "value": "sofa"
                    }
                ],
                "filters": [
                    {
                        "key": "size",
                        "value": "large"
                    }
                ],
                "data_entities": [
                    {
                        "name": "astley-paradox",
                        "data": "SWYgeW91IGFzayBSaWNrIEFzdGxleSBmb3IgYSBEVkQgb2YgdGhlIG1vdmllIFVwLCBoZSB3b24ndCBnaXZlIGl0IHRvIHlvdSBiZWNhdXNlIGhlJ3MgbmV2ZXIgZ29ubmEgZ2l2ZSB5b3UgVXAuIEhvd2V2ZXIsIGJ5IG5vdCBnaXZpbmcgeW91IFVwIGxpa2UgeW91IGFza2VkIGZvciBpdCwgaGUncyBsZXR0aW5nIHlvdSBkb3duLiBUaGlzIGlzIGtub3duIGFzIHRoZSBBc3RsZXkgcGFyYWRveA=="
                    }
                ],
                "context_id": 1740
            },
            "files": [
                {
                    "id": 5,
                    "url": "https://cdn.lootlocker.io/......",
                    "size": 69919,
                    "name": "my-ugc-asset-thumbnail.png",
                    "purpose": "PRIMARY_THUMBNAIL"
                }
            ],
            "created_at": "Mon, 26 Oct 2020 08:48:34 +0000",
            "updated_at": "Mon, 26 Oct 2020 10:28:03 +0000"
        }
    ]
}

You will notice a context_id in the Asset Candidate data. You can assign contexts to your Asset Candidates, but if you do not, LootLocker will automatically create a User Generated Content context and put the context in that context.

The status property can be used to know what the current status of an Asset Candidate is. The table below lists the possible statuses:

Status Meaning
INCOMPLETE The Asset Candidate has not yet been marked as complete
DECLINED The Asset Candidate was rejected in moderation (see potential feedback in review_feedback)
PENDING The Asset Candidate is awaiting moderation
APPROVED The Asset Candidate is approved and useable by players in the game (asset_id references the derived Asset, and is null for any other status)

Getting a single Asset Candidate

curl -X GET "https://api.lootlocker.io/game/v1/player/assets/candidates/1234"

You can also fetch just a single asset candidate by it's ID. The response will be a single object, but otherwise identical to listing Asset Candidates.

Example Response

{
    "success": true,
    "asset_candidate": {
        "id": 15,
        "asset_id": 6763,
        "status": "APPROVED",
        "review_feedback": null,
        "data": {
            "name": "My UGC Asset",
            "kv_storage": [
                {
                    "key": "kv-test",
                    "value": "great success"
                }
            ],
            "filters": [
                {
                    "key": "filter-test",
                    "value": "great success"
                }
            ],
            "data_entities": [
                {
                    "name": "Entity test",
                    "data": "flergen dergen hergen"
                }
            ],
            "context_id": 1740
        },
        "files": [],
        "created_at": "Tue, 17 Nov 2020 12:56:58 +0000",
        "updated_at": "Tue, 17 Nov 2020 12:58:25 +0000"
    }
}

Adding Files to Asset Candidates

curl -L -X POST 'https://api.lootlocker.io/game/v1/player/assets/candidates/1234/file' \
-H 'x-session-token: 17a76ed97be5224978c325m329bd4ccf1ee8b753' \
-F 'file=@/path/to/file.ext' \
-F 'purpose=PRIMARY_THUMBNAIL'

When adding a file to an Asset Candidate you need to supply the file in a property called file along with a purpose to let LootLocker know what to do with the file.

File Purposes

Purpose Used For
PRIMARY_THUMBNAIL The Primary Thumbnail shown in the LootLocker interface for moderation and curation purposes
THUMBNAIL Any extra images you want to expose to the LootLocker interface
FILE Any file you need to represent the content in your game client

Example Response

{"success": true}

Removing Files from an Asset Candidate

curl -X DELETE "https://api.lootlocker.io/game/v1/player/assets/candidates/1234/file/1234"

Deleting a file is done by referencing the Asset Candidate and the File by their respective ID's in the URL.

Example Response

{"success": true}

Missions

Getting All Missions

curl -X GET "https://api.lootlocker.io/game/v1/missions"

When getting all missions, you will receive data to set up the missions in the map too. You only get this data (checkpoints), if the player has access to this mission. You can check if a player has access to a mission by looking at the boolean player_access. The segment_time field that will be returned with each checkpoint is the time-between-checkpoint, which you can use to let the player know how they're doing compared to their last run. As you can see in the example, the segment_time property is not guaranteed to be there. It will however most likely be there for all checkpoints in one mission, unless the mission has been updated since the player last played it.

The best_goal property will hold a string with the name of the best goal the player have attained. If they have never played this mission or never reached a goal, it will be null.

As you can see in the example JSON, goals have an assets attribute. This is an array containing objects of assets that will be rewarded the first time the player reaches this goal. See example structure under the gold goal.

{
    "success": true,
    "missions": [
        {
            "mission_id": 1,
            "asset_id": 912,
            "rounds": 0,
            "round_length": "0",
            "difficulty_name": null,
            "difficulty_multiplier": null,
            "difficulty_color": "336699",
            "difficulty_id": 1,
            "goals": {
                "gold": {
                    "goal": "00:20:00",
                    "points": "400",
                    "assets": [
                        {
                            "variation_id": 1,
                            "asset": {...}
                        }
                    ]
                },
                "silver": {
                    "goal": "00:30:00",
                    "points": "200",
                    "assets": []
                },
                "bronze": {
                    "goal": "00:35:00",
                    "points": "100",
                    "assets": []
                }
            },
            "checkpoints": [
              {
                "index": 1,
                "time": 18510,
                "your_key": "your value",
                "your_second_key": "your second value"
              },{
                "index": 2,
                "your_key": "your value",
                "your_second_key": "your second value"
              }
            ],
            "player_access": true,
            "best_goal": "bronze"
        }
    ]
}

Getting A Single Mission

curl -X GET "https://api.lootlocker.io/game/v1/mission/42"

This endpoint is very similar to the Getting All Missions endpoint, in that it returns the same mission structure, but instead of a property called missions holding an array of missions, there is a property called mission, holding just one mission.

{
    "success": true,
    "mission": {
        "mission_id": 1,
        "asset_id": 912,
        "rounds": 0,
        "round_length": "0",
        "difficulty_name": null,
        "difficulty_multiplier": null,
        "difficulty_color": "336699",
        "difficulty_id": 1,
        "goals": {
            "gold": {
                "goal": "00:20:00",
                "points": "400",
                "assets": [
                    {
                        "variation_id": 1,
                        "asset": "Full asset representation, as returned everywhere else."
                    }
                ]
            },
            "silver": {
                "goal": "00:30:00",
                "points": "200",
                "assets": []
            },
            "bronze": {
                "goal": "00:35:00",
                "points": "100",
                "assets": []
            }
        },
        "checkpoints": [
          {
            "index": 1,
            "time": 18510,
            "your_key": "your value",
            "your_second_key": "your second value"
          },{
            "index": 2,
            "your_key": "your value",
            "your_second_key": "your second value"
          }
        ],
        "player_access": true,
        "best_goal": "bronze"
    }
}

Starting Mission

curl -X POST "https://api.lootlocker.io/game/v1/mission/1/start"

When starting a mission, you need to call this endpoint. From this endpoint you will get a signature back, which you need to use to sign the mission end call.

{
  "success": true,
  "signature": "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"
}

Finishing Mission

curl -X POST "https://api.lootlocker.io/game/v1/mission/1/end" \
-H "Content-Type: application/json" \
-d "{\"signature\": \"eee411109a229046154bc9d75265a9ccb23a3a9c\", \"payload\": {\"finish_time\": \"02:23:255\", \"finish_score\": \"125\", \"checkpoint_times\": [{\"index\": 1, \"time\": 571613}]}}"

When finishing the mission, you send a POST request to this endpoint. Your payload will hold data that's needed to calculate the score. You should calculate the score on your end, but you should correct your result to what you get from the response of this request, as that is what will be used in the backend.

If your mission is time based, you can send along checkpoint times, referenced as times. These are reported in milliseconds, and as a difference between two checkpoints only, summing these up should equal the total time of the mission. The backend will automatically store these for returning when loading missions. The data will only be updated if the total time is better than what's on file.

{
  "success": true,
  "score": 450,
  "check_grant_notifications": true
}

The check_grant_notifications field serves the same function as in the authentication call, meaning that if it's true, you should check the player asset notification endpoint for new notifications. You can do so immediately in this case, unlike the authentication call.

You do not have to send both finish_time and finish_score in calls, if you instead prefer to keep track of which type of mission is using what kind of goal, but you can simply just send both.

Signing Your Mission

Signing has to be done by concatenating the JSON string, the signature and the players backend id, and then hash it using SHA1.

# Assuming the three parts are
# 1: JSON = {"finish_time": "02:23:255", "finish_score": "125"}
# 2: Signature = 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
# 3: player_id = 66c18e45974889b4d0ecf3e92f6036ee9d2d50ee

sha1({"finish_time": "02:23:255", "finish_score": "125"}86f7e437faa5a7fce15d1ddcb9eaeaea377667b866c18e45974889b4d0ecf3e92f6036ee9d2d50ee) = 5d23383d582868ded525ee73d455d4d4b6d9592d

The order should be JSON string signature player_id.

The first part of the concatenated string is the JSON bit. That should only contain the object inside the payload property.

The second part is the signature you obtained from the Starting Mission endpoint.

The third part should be the player_id that you get when starting the session.

Once you've concatenated the three parts and hashed the resulting string, you should put it in a JSON object with the key signature, along side the payload property.

Drop Tables

Compute and Lock Drop Table

curl -X POST "https://api.lootlocker.io/game/v1/player/droptables/2/compute"

When you wish to evaluate a drop table and lock the drops from it in place, you call this endpoint. The response will hold information on the assets that are dropped, and can be picked up using the Pick endpoint.

The response is kept light to minimise resource usage, but if you need the full representation of the asset, you can include a GET style parameter in the url ?asset_details=true, and an additional asset property will be returned, with the full asset representation.

If you use tags with your drop tables, you can include a tag to only include groups and drops tagged with this tag in the caluclation. The tag is included by adding it as a GET style parameter: ?tag=skeleton.

Example Response

{
    "success": true,
    "items": [
        {
            "asset_id": 520,
            "asset_variation_id": null,
            "asset_rental_option_id": null,
            "id": 3
        }
    ]
}

The ID in the URL is the instance_id of the drop table asset from the players inventory.

Once a drop table has been computed and locked, there is a 24 hour guarantee that the pick endpoint will work. After this period, the drop table asset instance and it's locked drops may will be removed from the players inventory.

Pick Drops from Drop Table

curl -X POST "https://api.lootlocker.io/game/v1/player/droptables/2/pick" \
    -H "Content-Type: application/json" \
    -d "{\"picks\": [3]}"

When picking the drops to claim from a locked drop table, you send a payload along with the request, containing the ID's of the drops from the Compute endpoint. This payload has the key picks which contain an array of the ID's you want to pick. If you want to pick up nothing, you can send an empty array.

The response from this request contains the full asset of all the picked drops. See Getting Asset List for the full structure.

Example Response

{
    "success": true,
    "items": [
        {
            "instance_id": 487,
            "variation_id": null,
            "rental_option_id": null,
            "quantity": 1,
            "asset": {...}
        }
    ]
}

Maps

Getting All Maps

curl -X GET "https://api.lootlocker.io/game/v1/maps"

Getting all maps will return the simplest representation of a map, simply providing you with an asset_id to get the name, thumbnail etc. Maps also contain the spawn points.

Example response

{
    "success": true,
    "maps": [
        {
            "map_id": 1,
            "asset_id": 938,
            "spawn_points": [
                {
                    "asset_id": 966,
                    "position": null,
                    "rotation": null,
                    "cameras": [
                        {
                            "position": "12958181",
                            "rotation": "9591885818"
                        }
                    ],
                    "player_access": false
                },{
                    "asset_id": 967,
                    "position": "9157757101045",
                    "rotation": "958176717818238",
                    "cameras": [
                        {
                            "position": "12958181",
                            "rotation": "9591885818"
                        }
                    ],
                    "player_access": true
                }
            ],
            "player_access": false
        },
        {
            "map_id": 2,
            "asset_id": 950,
            "spawn_points": [
                {
                    "asset_id": 966,
                    "position": null,
                    "rotation": null,
                    "cameras": [
                        {
                            "position": "12958181",
                            "rotation": "9591885818"
                        }
                    ],
                    "player_access": false
                },{
                    "asset_id": 967,
                    "position": "9157757101045",
                    "rotation": "958176717818238",
                    "cameras": [
                        {
                            "position": "12958181",
                            "rotation": "9591885818"
                        }
                    ],
                    "player_access": true
                }
            ],
            "player_access": false
        },
        {
            "map_id": 3,
            "asset_id": 965,
            "spawn_points": [
                {
                    "asset_id": 966,
                    "position": null,
                    "rotation": null,
                    "cameras": [
                        {
                            "position": "12958181",
                            "rotation": "9591885818"
                        }
                    ],
                    "player_access": false
                },{
                    "asset_id": 967,
                    "position": "9157757101045",
                    "rotation": "958176717818238",
                    "cameras": [
                        {
                            "position": "12958181",
                            "rotation": "9591885818"
                        }
                    ],
                    "player_access": true
                }
            ],
            "player_access": true
        }
    ]
}

Purchasing

Only some platforms support purchasing with hard currency. The below table provides an overview

Platform Supports Hard Currency Purchasing
Steam Yes
PSN Yes
Roblox No
iOS Yes
Android Yes

Purchase Call

Sending a request to this endpoint with asset information, will facilitate a purchase. If your game uses soft currency, it will check the players account balance and grant the assets to the player if there is coverage. If there is not coverage, an error will be returned.

There are two different kinds of purchases you can perform. A rental and a standard purchase. When doing a standard purchase, you only need the asset_id and potentially the variation_id properties. When buying a rental asset, you will be required to send at least the asset_id and rental_option_id parameters. The rental_option_id value is obtained from the assets call, just like the asset_id and the variation_id. To activate a rental, see Activating A Rental Asset

Normal purchase example

curl -X POST "https://api.lootlocker.io/game/v1/purchase" \
    -H "Content-Type: application/json" \
    -d "[{\"asset_id\": 56, \"variation_id\": 130},{\"asset_id\": 380, \"variation_id\": 616}]"

If your game does not use soft currency, or the assets you are buying are soft currency, the purchase will behave a few different ways depending on what platform the user is on:

Platform Action
Steam An overlay will be opened, asking the player to pay with their Steam Wallet.
PSN For PSN you will have had to initialize the purchase with the SDK for the PS4 first, and then call this endpoint to tell LootLocker to consume the entitlemnt on PSN.
iOS You have to complete an iOS In-App Purchase before calling the purchase endpoint in LootLocker. See iOS In-App Purchases for more information.
Android Similar to iOS, you have to complete an In-App Pruchase before calling the purchase endpoint in LootLocker. See Android In-App Purchases for more information.

Rental example

curl -X POST "https://api.lootlocker.io/game/v1/purchase" \
    -H "Content-Type: application/json" \
    -d "[{\"asset_id\": 56, \"variation_id\": 130, \"rental_option_id\": 47}]"

You will get an order_id in the response. This ID should be used to poll the order status until you get a final answer from it. See the polling order status endpoint

The response will let you know if any form of overlay have been opened. Keep in mind, only if you have success = true and overlay = false can you safely assume that the purchase has been successful. If overlay is true, you should check the order status to know the status of the order. Once you know the purchase was successful you should issue a call to the player inventory endpoint to update the client inventory data.

The external_identifiers field in the asset responses, is either null or an object, letting you know how to identify this same asset on other platforms. In the given examples PSN is used, and CRED01 is the entitlementLabel/entitlementId on Sony's side. Use this to know what credit package a player has bought through their servers when selecting which asset to purchase.

Example response, with no overlay opened

{
    "success": true,
    "overlay": false,
    "order_id": 583,
}

iOS In-App Purchases

iOS In-App Purchase verification example

curl -X POST "https://api.lootlocker.io/game/v1/purchase" \
    -H "Content-Type: application/json" \
    -d "[{\"receipt_data\": \"base64 encoded app store receipt\"}]"

In-App Purchases on iOS are different from other purchases in LootLocker in the way that they don't take asset information, but instead requires a receipt from Apple that LootLocker will then verify and map to the correct asset information. This receipt is returned when reading Bundle.main.appStoreReceiptURL from your application.

For any assets that should be purchasable multiple times, you should use consumable IAP's on Apples side, and once you have a successful purchase from LootLocker, call finishTransaction on the transaction in the client, to let Apple know to consume the purchase.

Once the request returns successfully you should issue a call to the player inventory endpoint and/or the currency balance endpoint to update the client inventory and balance data.

Example response for iOS In-App Purchase

{
    "success": true,
    "overlay": false,
    "order_id": 583,
}

Android In-App Purchases

Android In-App Purchase verification example

curl -X POST "https://api.lootlocker.io/game/v1/purchase" \
    -H "Content-Type: application/json" \
    -d "[{\"asset_id\": 1234, \"purchase_token\": \"purchase_token_supplied_by_google_play_store\"}]"

Purchases on Android are slightly different from other purchases, in that they take a purchase_token property besides the asset information. In the example here, we are buying in-game currency, which only requires an asset_id and the token. The purchase_token is obtained through the Google Play store, when performing an In-App Purchase.

Once the request returns successfully you should issue a call to the player inventory endpoint and/or the currency balance endpoint to update the client inventory and balance data.

Polling Order Status

curl -X GET "https://api.lootlocker.io/game/v1/purchase/23"

This call will let you know the current status of an order. If you get a response that is considered final, you should issue a call to the player inventory endpoint if you're in a context where the inventory might change.

Example response

{
    "success": true,
    "status": "closed"
}

The following statuses can currently be returned:

Status Final Description
open No The order is being processed
closed Yes The order have been processed successfully
refunded Yes The order has been refunded
canceled Yes The order has been canceled
failed Yes The order failed

Get Order Details

curl -X GET "https://api.lootlocker.io/game/v1/purchase/23/details"

This endpoint lets you inspect an order and see what products is contained, as well as the order status. For a description of order statuses, please see the table under Polling Order Status.

If you do not want to return the products, you can add a flag to the url that removes them: ?no_products=true, in which case the products property will be null.

Example Response

{
    "success": true,
    "order_status": "succeeded",
    "products": [
        {
            "instance_id": 458,
            "variation_id": null,
            "rental_option_id": null,
            "acquisition_source": "purchase_unit",
            "asset": {...}
        }
    ]
}

Get Order Details By Platform Transaction ID

curl -X GET "https://api.lootlocker.io/game/v1/purchase/transaction/1000000673097863/details"

This endpoint is identical to Get Order Details, except that instead of the order id, you can use the First Party Platforms Transaction ID.

The response is identical as well.

Activating A Rental Asset

curl -X POST "https://api.lootlocker.io/game/v1/asset/instance/57613/activate"

Once you have purchased a rental asset, you need to activate the rental for it to become available for the player. This endpoint achieves that.

The successful response from this endpoint, will contain just one property, time_left, which is seconds left until the rental expires. You should keep a timer running to deactivate the asset for the player once it runs out.

Example response

{
    "success": true,
    "time_left": 86400
}

Trigger Events

Triggering an Event

curl -X POST "https://api.lootlocker.io/game/v1/player/trigger"
  -H "Content-Type: application/json"
  -d "{\"name\": \"your trigger name here\"}"

Trigger events can be configured through the Admin API, or in the LootLocker Management Console. There you can set rewards for triggering an event and so forth.

Rewards can be either XP or assets (It can also be both). If assets have been granted, the endpoint will return the granted assets in the granted_assets property, in the standard full asset object format.

As you can see in the example response, XP is a little more complicated, as it will return in the same format as the Submit Score endpoint.

All of the properties will always be present

Example response

{
    "success": true,
    "check_grant_notifications": true,
    "xp": {
        "previous": 1234,
        "current": 2468
    },
    "levels": [
        {
            "level": 1,
            "xp_threshold": 1000
        },
        {
            "level": 2,
            "xp_threshold": 3000
        },
        {
            "level": 3,
            "xp_threshold": 6000
        }
    ],
    "granted_assets": [
        {...}
    ]
}

Listing Triggered Trigger Events

curl -X GET "https://api.lootlocker.io/game/v1/player/triggers"

This endpoint lists the triggers that a player have already completed.

Use this list to know which triggers to not call from the game client.

Example Response

{
    "success": true,
    "triggers": [
        "enterArea.area_east_sub_1",
        "enterArea.area_east_sub_10",
        "enterArea.area_east_sub_11",
        "enterArea.area_east_sub_2"
    ]
}

Collectables

Collectables and triggers are very similar functionalities. The difference is that collectables are nested in 3 layers (Collectable, Groups and Items). Each entity in can have a reward that's triggered when all nested entities are completed (for items this is when the item is collected).

Getting Collectables

curl -X GET "https://api.lootlocker.io/game/v1/collectable

This endpoint will return all the collectables a game has set up. It will hold a set of Collectables, with Groups inside which in turn contain Items. Items are what you collect as a player. The Groups and the Collectable are containers, that serve to give a segmented completion percentage and to give rewards to the player at differet completion stages.

Each level (Collectables, Groups and Items) can contain rewards for the player. These rewards are contained in rewards for each item. An empty array means no rewards. There is a flag grants_all_rewards, which signifies if the rewards will be all granted to the player, or if one of the rewards will be randomly selected for the reward. Each reward contains a full representation of an asset, along with the asset_variation_id or asset_rental_option_id that will be granted to the player.

Even collected Items are returned, with a boolean collected set to true. This is done to make it easier to remove them from your world, give them a different look, or make sure you do not collect them again.

Additionally there is a boolean just_collected to let you know if this collectable item was collected in a call issued to the Collecting an Item endpoint. It will always be false when requesting the list of collectables, and only be true if the call was successful in collecting an item.

Example response

{
    "success": true,
    "collectables": [
        {
            "name": "CarsDriven",
            "groups": [
                {
                    "name": "SUVs",
                    "completion_percentage": 50,
                    "items": [
                        {
                            "name": "Sporty",
                            "collected": true,
                            "rewards": [],
                            "grants_all_rewards": false,
                            "just_collected": false
                        },
                        {
                            "name": "Practical",
                            "collected": false,
                            "rewards": [],
                            "grants_all_rewards": false,
                            "just_collected": false
                        }
                    ],
                    "rewards": [],
                    "grants_all_rewards": false
                },
                {
                    "name": "Bugs",
                    "completion_percentage": 0,
                    "items": [
                        {
                            "name": "Dune",
                            "collected": false,
                            "rewards": [
                                {
                                    "asset": {...},
                                    "asset_variation_id": 7010,
                                    "asset_rental_option_id": null
                                }
                            ],
                            "grants_all_rewards": true,
                            "just_collected": false
                        }
                    ],
                    "rewards": [],
                    "grants_all_rewards": false
                }
            ],
            "completion_percentage": 33,
            "rewards": [],
            "grants_all_rewards": false
        }
    ]
}

Collecting an Item

curl -X POST "https://api.lootlocker.io/game/v1/collectable" \
    -H "Content-Type: application/json" \
    -d "{\"slug\": \"CarsDriven.Bugs.Dune\"}"

Collecting an Item is done by calling this endpoint with a payload equal to the slug of the Item.

The slug is a combination of the name of the Collectable, the Group and the Item. Simply concatenate them with a . as a seperator. In the example we're collecting the Item Dune in the Group Bugs that belongs to the Collectable CarsDriven.

Once an Item is collected, you will get a response back identical to the one you get from Getting Collectables, with the addition of a field at the root level called check_grant_notifications. If this field is true, you should check the players player asset grant notifications.

Messages

Get Messages

curl -X GET "https://api.lootlocker.io/game/v1/messages"

The messages Game System allows you to send messages to your players, such as news and promotions.

Messages are somewhat personalized for the player, in that they has a new property that tells if the message is new since the players last session.

Example Response

{
    "success": true,
    "messages": [
      {
        "title": "Whiteridge has opened!",
        "published_at": "2017-09-08 09:36:25",
        "body": "Welcome to Whiteridge! The small mountain town with lots of stuff for your skiing pleasure...",
        "summary": "Today we're releasing a new level called Whiteridge.\r\n\r\nWhiteridge is an urban level with lots of jumps and features to hit.",
        "category": "levels",
        "alert": true,
        "new": true,
        "action": "",
        "image": "https://url/to/file.dds"
      }
    ]
}

Crashes

Submitting a Crash Log

# Uploading a crash log with bash
curl -X -i -F log=@path/to/your/log/file.zip "https://api.lootlocker.io/game/v1/crash" \
  -d "version=game_version" \
  -H "x-session-token=your_session_token"

Submitting a crash works much like most other requests do. There are two exceptions, a file upload, and the request does not take a JSON body, but instead uses POST fields.

The parameters for this call is as follows:

Parameter Required Description
log Yes Your log file
game_version no The version of the game at crash time
type_identifier no A crash identifier you create
local_crash_time no The time the crash happened on the users computer

The type_identifier property is special. You should compute a string between 1 and 255 characters, that uniquely identifies this type of crash. Using this LootLocker will alert you when too many crashes of the same type happen in a short span.

If you are able to submit the crash in a crashed state, you can do that, but the general idea behind this is to submit it on the next launch of your game.

Errors

Errors are hinted with HTTP Status codes. 200 is OK, the rest that we're using is listed below here. You should be able to handle all of these in your integration.

Error Code Meaning
400 Bad Request -- Your request has an error
402 Payment Required -- Payment failed. Insufficient funds, etc.
401 Unauthroized -- Your session_token is invalid
403 Forbidden -- You do not have access
404 Not Found
405 Method Not Allowed
406 Not Acceptable -- Purchasing is disabled
409 Conflict -- Your state is most likely not aligned with the servers.
429 Too Many Requests -- You're being limited for sending too many requests too quickly.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're either offline for maintenance, or an error that should be solvable by calling again later was triggered.

Deprecations

When the API changes and an endpoints reaches the end of it's life, it will send a X-Endpoint-Deprecated: true header with each response, until it's taken out of service. A list of currently deprecated endpoints will also be maintained here, along with their EOL date, which is 6 months after they have been deprecated.

If the below table is empty, there aren't currently any deprecations.

Endpoint Request Type EOL Replaced By