Skip to content
@deckyard/steam

Cheatsheet

Every export, by topic. The guides linked from the introduction explain the background; this page lists signatures, values and fields.

jennifer
import "@deckyard/steam/" as steam;
def c as steam.Client init steam.client("YOUR-KEY");   # "" for the keyless endpoints

Every failure is Error{kind: "steam"}. Each call that takes a Client also throws on a transport failure or a non-JSON reply; the Notes column lists the other conditions. Arguments are checked before any request.

Which calls need a key

Get a key at https://steamcommunity.com/dev/apikey. Valve rate-limits per key. A key-gated call on a keyless client throws before any request.

KeylessNeeds a key
newsForApp, newsForAppFeedsplayerSummaries, playerSummary, friendList, playerBans, playerBan, resolveVanityUrl, userGroups
currentPlayers, globalAchievementRarityownedGames, ownedGameCount, recentlyPlayedGames, steamLevel, badges, badgeProgress, sharedGameLender
appDetails, appDetailsMany, appPrices, packageDetails, featuredplayerAchievements, userStats, gameSchema
priceOverviewappList, appListPage
publishedFileDetails, publishedFile, collectionDetails, collectionItemstradeOffersSummary, tradeOffers, tradeOffer, assetPrices
upToDateCheck, serversAtAddress, serverInfo, supportedApiListgameServerAccounts, gameServerInfo, queryLoginToken
resolveAccount with an idresolveAccount with a vanity name

call sends the key when the client has one. The id, URL, money and markup helpers make no request.

Client

FunctionReturnsNotes
client(apiKey)Clientkey trimmed; English, US, USD, 15000 ms timeout, 2 retries, 500 ms backoff; STEAM_VERBOSE = 1, true, yes or on sets verbose
clientFromEnv()Clientclient(STEAM_API_KEY), then STEAM_LANGUAGE and STEAM_COUNTRY when not blank; throws when STEAM_COUNTRY is not two letters
withLanguage(c, language)Clientlowercased; throws when blank
withCountry(c, countryCode)Clientuppercased; throws unless two letters
withCurrency(c, currency)Clienta CURRENCY_* id; throws unless positive
withTimeout(c, timeoutMs)Clientidle timeout per read; 0 means http's 30000 ms, not DEFAULT_TIMEOUT_MS; throws when negative
withRetries(c, retries)Clientretries of a 429 or 5xx; 0 disables; throws when negative
withBackoff(c, backoffMs)Clientfirst retry delay, doubled per attempt, raised to a numeric Retry-After, capped at 30 s; 0 means http's 250 ms, not DEFAULT_BACKOFF_MS; throws when negative
setVerbose(c, enabled)Clientprint each request before sending it
isVerbose(c)bool
hasKey(c)booltrue for a non-empty key
call(c, service, method, version, params)json.ValueGET any Web API method; throws when a name is not letter-initial letters and digits, the version is not positive, or the status is not 2xx

Builders return a copy: $c = steam.withCountry($c, "DE");.

Verbose output, one line per request. key, access_token, token and login_token print as <redacted>:

steam> GET https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?steamids=76561197960287930&key=<redacted>
steam> POST https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1/?itemcount=1&publishedfileids%5B0%5D=450814997
ConstantValueMeaning
API_BASE"https://api.steampowered.com"Web API host
STORE_BASE"https://store.steampowered.com"storefront host
COMMUNITY_BASE"https://steamcommunity.com"community host (profiles, market, Workshop)
MEDIA_BASE"https://cdn.akamai.steamstatic.com"artwork host
DEFAULT_TIMEOUT_MS15000a new client's idle timeout
DEFAULT_RETRIES2a new client's retry budget
DEFAULT_BACKOFF_MS500a new client's first retry delay
MAX_RESPONSE_BYTES33554432body cap (32 MiB)
CURRENCY_USD1US dollar, a new client's currency
CURRENCY_GBP2pound sterling
CURRENCY_EUR3euro
CURRENCY_CHF4Swiss franc
CURRENCY_RUB5Russian rouble
CURRENCY_PLN6Polish zloty
CURRENCY_BRL7Brazilian real
CURRENCY_JPY8Japanese yen
CURRENCY_CAD20Canadian dollar
CURRENCY_AUD21Australian dollar

Client

FieldMeaning
key as stringWeb API key, "" for keyless use
language as stringl / language parameter, e.g. "english"
countryCode as stringstorefront country, e.g. "US"
currency as intwallet currency id for market prices
timeoutMs as intidle timeout in milliseconds
retries as intretry budget for a 429 or 5xx
backoffMs as intfirst retry delay in milliseconds
verbose as boolprint requests

Steam ids

Every steamId argument in the deck accepts all three notations.

FunctionReturnsNotes
parseSteamId(id64)SteamIdthrows when not a 64-bit id
toSteamId64(parts)stringignores parts.id64; throws when a field is outside the range Steam issues
isSteamId(text)bool17 to 20 digits, universe 1-5, account type at most 10
isSteamId64(text)boola personal account only
looksLikeSteamId(text)boolnormalizeSteamId would accept it
normalizeSteamId(text)stringany notation to the id64; throws when none fits
toSteamId2(id64)string"STEAM_1:0:11101"; throws for a non-personal account
toSteamId3(id64)string"[U:1:22202]"; a group is [g:1:W]
fromSteamId2(text)stringSTEAM_0 reads as universe 1
fromSteamId3(text)stringbrackets optional; honours [U:1:W:instance]
accountId(id64)intthe 32-bit account number ("friend id")
steamId64FromAccountId(account)stringpersonal account; throws outside 1 to 4294967295
profileUrl(id64)stringhttps://steamcommunity.com/profiles/<id64>; any notation
vanityProfileUrl(vanity)stringhttps://steamcommunity.com/id/<name>, name percent-encoded
groupUrl(id64)stringhttps://steamcommunity.com/gid/<id64>
accountTypeName(accountType)string"individual", "group", ...; "unknown" outside 0-10
ConstantValueMeaning
INDIVIDUAL_BASE76561197960265728id64 of personal account number 0
CLAN_BASE103582791429521408id64 of group number 0
UNIVERSE_PUBLIC1the public universe
UNIVERSE_MAX5highest universe Steam issues
ACCOUNT_INDIVIDUAL1a person
ACCOUNT_MULTISEAT2multiseat (cyber-cafe) account
ACCOUNT_GAME_SERVER3persistent game server
ACCOUNT_ANON_GAME_SERVER4anonymous game server
ACCOUNT_CONTENT_SERVER6content server
ACCOUNT_CLAN7group
ACCOUNT_CHAT8chat room
ACCOUNT_ANON_USER10anonymous user

SteamId

FieldMeaning
id64 as string17-digit decimal id
universe as intbits 56-63; 1 = public
accountType as intbits 52-55; 1 = individual, 7 = group
instance as intbits 32-51; 1 for a desktop account
accountId as intbits 0-31, the "friend id"
jennifer
steam.toSteamId2("76561197960287930");     # STEAM_1:0:11101
steam.fromSteamId3("[g:1:4]");             # 103582791429521412 (a group)
steam.accountTypeName(steam.parseSteamId("103582791429521412").accountType);   # group

Users (ISteamUser)

FunctionReturnsNotes
playerSummaries(c, steamIds)list of PlayerSummary1 to 100 ids; unknown accounts are left out
playerSummary(c, steamId)PlayerSummarythrows when the account is unknown
friendList(c, steamId)list of Friendoldest first; empty when private
playerBans(c, steamIds)list of PlayerBan1 to 100 ids
playerBan(c, steamId)PlayerBanthrows when there is no record
resolveVanityUrl(c, vanity)stringid64, "" when no profile has the name
resolveAccount(c, text)stringid in any notation, vanity name or /id/<name> URL; only a vanity name costs a request; throws when nothing matches
userGroups(c, steamId)list of stringgroup id64s; empty when private
personaStateName(state)string"offline", "online", "busy", ...; "unknown" otherwise
visibilityName(visibility)string"private", "friends only", "public"; "unknown" otherwise
isPublic(player)boolcommunityVisibilityState is VISIBILITY_PUBLIC
isOnline(player)boolany state but offline
isInGame(player)boolgameId is neither "" nor "0"
ConstantValueMeaning
PERSONA_OFFLINE0signed out
PERSONA_ONLINE1signed in
PERSONA_BUSY2busy
PERSONA_AWAY3away
PERSONA_SNOOZE4idle long enough to snooze
PERSONA_LOOKING_TO_TRADE5looking to trade
PERSONA_LOOKING_TO_PLAY6looking to play
VISIBILITY_PRIVATE1only the account itself
VISIBILITY_FRIENDS2friends
VISIBILITY_PUBLIC3everyone
RELATIONSHIP_FRIEND"friend"the friend-list relationship
SUMMARY_BATCH100largest playerSummaries / playerBans batch

PlayerSummary

Only steamId, personaName, profileUrl, the avatars and personaState are guaranteed. The rest is filled in only for a public profile that publishes the field, so "" or 0 means "not shared".

FieldMeaning
steamId as stringid64
personaName as stringdisplay name
profileUrl as stringcommunity profile URL
avatar as string32x32 avatar URL
avatarMedium as string64x64 avatar URL
avatarFull as string184x184 avatar URL
avatarHash as stringhash shared by the avatar URLs
personaState as inta PERSONA_* value
communityVisibilityState as inta VISIBILITY_* value
profileState as int1 once a community profile is configured
lastLogoff as intUnix time of the last sign-out
commentPermission as intnon-zero when strangers may comment
realName as stringreal name
primaryClanId as stringid64 of the primary group
timeCreated as intUnix time the account was created
personaStateFlags as intclient flags
countryCode as stringtwo-letter country
stateCode as stringregion within the country
cityId as intSteam's city id
gameId as stringapp being played, "" or "0" when none
gameExtraInfo as stringtitle being played
gameServerIp as stringserver being played on

Friend

FieldMeaning
steamId as stringthe friend's id64
relationship as string"friend"
friendSince as intUnix time of the friendship

PlayerBan

FieldMeaning
steamId as stringid64
communityBanned as boolbanned from community features
vacBanned as boolat least one VAC ban
vacBans as intVAC bans across all games
gameBans as intdeveloper-issued game bans
daysSinceLastBan as int0 when never banned
economyBan as string"none", "probation" or "banned"

Player (IPlayerService)

These need the account's game details to be public; a private library comes back empty, not as an error.

FunctionReturnsNotes
ownedGames(c, steamId, includeAppInfo, includeFreeGames)list of OwnedGameincludeAppInfo adds name and icon; without includeFreeGames played free-to-play titles are left out
ownedGameCount(c, steamId)intcounts played free-to-play titles; 0 when private
recentlyPlayedGames(c, steamId, count)list of OwnedGamelast two weeks, most recent first; throws unless count is positive
steamLevel(c, steamId)int0 when hidden
badges(c, steamId)BadgeCollection
badgeProgress(c, steamId, badgeId)list of BadgeQuestthrows unless badgeId is positive
sharedGameLender(c, steamId, appId)stringthe Family Sharing lender's id64, "" when owned
playtimeHours(minutes)floathours, rounded to one decimal
totalPlaytime(games)intsum of playtimeForever, minutes
mostPlayed(games, count)list of OwnedGamelongest playtimeForever first; throws unless count is positive
unplayed(games)list of OwnedGamezero playtimeForever
gameIconUrl(appId, iconHash)string"" for an empty hash

OwnedGame

FieldMeaning
appId as intapp id
name as stringtitle, "" without app info
playtimeForever as intlifetime minutes
playtimeTwoWeeks as intminutes in the last two weeks
playtimeWindows as intlifetime minutes on Windows
playtimeMac as intlifetime minutes on macOS
playtimeLinux as intlifetime minutes on Linux
playtimeDeck as intlifetime minutes on a Steam Deck
iconHash as stringicon hash for gameIconUrl, "" without app info
hasCommunityVisibleStats as boolthe game publishes stats
lastPlayed as intUnix time of the last launch, 0 when never

Badge

FieldMeaning
badgeId as intbadge id
appId as intapp, 0 for a Steam-wide badge
level as intbadge level
completionTime as intUnix time the level was reached
xp as intexperience it is worth
scarcity as intaccounts holding it
communityItemId as stringcommunity item id
borderColor as int1 for a foil badge

BadgeCollection

FieldMeaning
playerLevel as intSteam level
playerXp as inttotal experience
xpNeededToLevelUp as intexperience missing for the next level
xpNeededCurrentLevel as intexperience the current level started at
badges as list of Badgeevery badge held

BadgeQuest

FieldMeaning
questId as inttask id
completed as booldone

Stats (ISteamUserStats)

FunctionReturnsNotes
playerAchievements(c, steamId, appId)PlayerAchievementslocalized; throws when Steam refuses (private profile, unowned game, no stats)
userStats(c, steamId, appId)list of StatValueempty when the game keeps none
globalAchievementRarity(c, appId)list of AchievementRaritykeyless; internal names
currentPlayers(c, appId)intkeyless; throws when Steam has no count
gameSchema(c, appId)GameSchemalocalized
unlockedCount(achievements)int
completionPercent(achievements)float0.0 to 100.0; 0.0 for none
lockedAchievements(achievements)list of Achievementnot yet earned
rarest(rarities, count)list of AchievementRaritylowest percentage first; throws unless count is positive

Achievement

FieldMeaning
apiName as stringinternal name
achieved as boolunlocked
unlockTime as intUnix time, 0 while locked
name as stringdisplay name
description as string"" while a hidden achievement is locked

PlayerAchievements

FieldMeaning
steamId as stringaccount
appId as intgame
gameName as stringtitle
achievements as list of Achievementevery achievement, locked or not

StatValue

FieldMeaning
name as stringinternal name
value as intcurrent value

AchievementRarity

FieldMeaning
name as stringinternal name, to join with SchemaAchievement.name
percent as floatshare of players, 0-100

SchemaAchievement

FieldMeaning
name as stringinternal name
displayName as stringlocalized title
description as stringlocalized description, "" when hidden
hidden as booldescription withheld until unlocked
icon as stringunlocked icon URL
iconGray as stringlocked icon URL

SchemaStat

FieldMeaning
name as stringinternal name
displayName as stringlocalized label, "" when none
defaultValue as intstarting value

GameSchema

FieldMeaning
appId as intgame
gameName as stringtitle
gameVersion as stringschema version
achievements as list of SchemaAchievementdefined achievements
stats as list of SchemaStatdefined statistics

Apps (IStoreService, ISteamApps, ISteamWebAPIUtil)

FunctionReturnsNotes
appListPage(c, lastAppId, maxResults)AppListPagegames only; lastAppId 0 to start; maxResults 1 to 50000
appList(c, maxPages)list of Apppages of 50000 until none are left or maxPages is reached
findApps(apps, term)list of Appcase-insensitive substring; throws on a blank term
appById(apps, appId)AppappId 0 and name "" when absent
upToDateCheck(c, appId, version)VersionCheckkeyless; throws on a negative version
serversAtAddress(c, address)list of GameServerkeyless; ip or ip:port; empty when none
serverInfo(c)ServerInfokeyless
supportedApiList(c)list of ApiMethodthe public methods, plus those the key unlocks
storePageUrl(appId)stringhttps://store.steampowered.com/app/<id>
headerImageUrl(appId)string<MEDIA_BASE>/steam/apps/<id>/header.jpg
capsuleImageUrl(appId)string<MEDIA_BASE>/steam/apps/<id>/capsule_231x87.jpg
ConstantValueMeaning
APPLIST_PAGE_MAX50000largest catalogue page

App

FieldMeaning
appId as intapp id
name as stringname

AppListPage

FieldMeaning
apps as list of Appthe entries
lastAppId as intpass as lastAppId for the next page
haveMore as boolanother page follows

VersionCheck

FieldMeaning
upToDate as boolthe version is current
versionIsListable as boolSteam still lists it
requiredVersion as intlowest version allowed to connect
message as stringSteam's explanation, "" when none

GameServer

FieldMeaning
address as stringip:port
appId as intgame
gameDir as stringgame directory, e.g. "tf"
region as intSteam region code
gamePort as intclient port
specPort as intSourceTV port, 0 when none
secure as boolVAC enabled
lan as boolLAN-only

ServerInfo

FieldMeaning
serverTime as intUnix time at Steam
serverTimeString as stringthe same, formatted by Steam

ApiMethod

FieldMeaning
interfaceName as stringe.g. "ISteamUser"
name as stringe.g. "GetPlayerSummaries"
version as intmethod version
httpMethod as string"GET" or "POST"
parameters as list of stringparameter names

News (ISteamNews)

FunctionReturnsNotes
newsForApp(c, appId, count, maxLength)list of NewsItemnewest first; maxLength 0 for whole bodies; throws unless count is positive or when maxLength is negative
newsForAppFeeds(c, appId, count, maxLength, feeds)list of NewsItemas newsForApp, from comma-separated feeds ("" for all)
plainText(markup)stringstrips HTML and BBCode, see news
summarize(text, maxChars)stringat most maxChars characters, cut at a word, ending in one …; throws unless maxChars is positive
ConstantValueMeaning
FEED_ANNOUNCEMENTS"steam_community_announcements"the game's own announcements
FEED_STEAM"steam_updates"Steam's editorial posts
MARKUP_SPAN512longest run, in code points, plainText reads as one tag
BLOCK_TAGSbr, p, div, li, ul, ol, tr, td, th, table, blockquote, h1-h6, hr, pre, list, olist, quote, code, *tags plainText replaces with a space
BBCODE_TAGSb, i, u, s, strike, url, img, list, olist, *, quote, code, noparse, h1-h3, hr, spoiler, table, tr, th, td, previewyoutube, dynamiclink, carousel, expand, video, steamwidget, randomboxesBBCode tags plainText removes
CLAN_IMAGE_TOKENS{STEAM_CLAN_LOC_IMAGE}, {STEAM_CLAN_IMAGE}image embeds plainText drops with their path

NewsItem

FieldMeaning
gid as stringunique id
title as stringheadline
url as stringwhere to read it
isExternalUrl as boolurl leaves Steam
author as stringposter, "" when none
contents as stringbody, HTML and/or BBCode
feedLabel as stringfeed label, e.g. "Community Announcements"
feedName as stringfeed name for feeds, e.g. "steam_community_announcements"
feedType as intSteam's feed type
date as intUnix time posted
appId as intgame

Store (store.steampowered.com)

Keyless and regional: the client's countryCode and language go with every request. One request per app id.

FunctionReturnsNotes
appDetails(c, appId)AppDetailsthrows when there is no record (delisted, region-locked, not an app)
appDetailsMany(c, appIds)list of AppDetailsids without a record are left out
appPrices(c, appIds)list of AppPriceone entry per id, found false without a record; throws on an empty list
packageDetails(c, packageId)PackageDetailsthrows unless positive, or when there is no record
featured(c)FeaturedLists
isDiscounted(price)booldiscountPercent > 0 and final < initial
savings(price)intinitial - final in minor units, 0 when not discounted
majorUnits(minorUnits)floatdivided by 100, yen included
discountLabel(price)stringe.g. "-66%", "" when not discounted

The id lists are checked in full before the first request; a transport failure throws rather than shortening the list.

ConstantValueMeaning
APPDETAILS_PATH"/api/appdetails"app record path
PACKAGEDETAILS_PATH"/api/packagedetails"package record path
FEATURED_PATH"/api/featured"featured lists path

Price

Amounts are ints in minor units. A free or unreleased title has a zeroed Price.

FieldMeaning
currency as stringISO code, e.g. "EUR"
initial as intundiscounted price
final as intcurrent price
discountPercent as int0 when none
initialFormatted as stringSteam's rendering of initial, "" at full price
finalFormatted as stringSteam's rendering of final, the one to show

Platforms

FieldMeaning
windows as boolWindows build
mac as boolmacOS build
linux as boolnative Linux build (Proton not counted)

AppDetails

FieldMeaning
appId as intapp id
name as stringtitle
kind as string"game", "dlc", "demo", "music", ...
requiredAge as intage gate, 0 when none
isFree as boolcosts nothing
shortDescription as stringblurb, HTML
aboutTheGame as stringlong description, HTML
supportedLanguages as stringlanguage list, HTML
headerImage as stringbanner URL
capsuleImage as stringcapsule URL
website as stringdeveloper site, "" when none
developers as list of stringdevelopers
publishers as list of stringpublishers
price as Pricezeroed when free or unreleased
platforms as Platformsbuilds
categories as list of stringe.g. "Multi-player"
genres as list of stringe.g. "Action"
dlc as list of intDLC app ids
metacriticScore as int0 when unscored
metacriticUrl as string"" when unscored
recommendations as intuser recommendations
achievementCount as intachievements defined
releaseDate as stringas Steam renders it
comingSoon as boolnot yet released

AppPrice

FieldMeaning
appId as intapp id
found as boolthe storefront had a record
free as boolfree to play
price as Pricezeroed when free or not found

PackageDetails

FieldMeaning
packageId as intpackage id
name as stringname
pageImage as stringstore image URL
apps as list of Appapps in it
price as Priceprice
platforms as Platformsbuilds
releaseDate as stringas Steam renders it
comingSoon as boolnot yet released

FeaturedApp

FieldMeaning
appId as intapp id
name as stringtitle
discounted as boolon sale
discountPercent as int0 when none
originalPrice as intundiscounted, minor units
finalPrice as intcurrent, minor units
currency as stringISO code
capsuleImage as stringwide capsule URL
headerImage as stringheader URL
windowsAvailable as boolWindows build
macAvailable as boolmacOS build
linuxAvailable as boolnative Linux build

FeaturedLists

FieldMeaning
largeCapsules as list of FeaturedAppfront-page banners, often empty outside a sale
windows as list of FeaturedAppfeatured for Windows
mac as list of FeaturedAppfeatured for macOS
linux as list of FeaturedAppfeatured for Linux

Market (steamcommunity.com/market)

FunctionReturnsNotes
priceOverview(c, appId, marketHashName)MarketPricekeyless; in the client's currency; found false when unpriced; roughly 20 requests a minute per address
marketListingUrl(appId, marketHashName)stringname percent-encoded
marketSearchUrl(appId, term)stringterm "" browses everything
currencyCode(currency)stringISO code of a CURRENCY_* id, "" for any other
parseMoney(text)floatlast . or , is decimal when 1 or 2 digits follow; 0.0 when unreadable
parseMoneyCents(text)intparseMoney x 100, rounded; 0 past MAX_MONEY_UNITS
parseCount(text)intdigits only; 0 when none or too large
ConstantValueMeaning
PRICEOVERVIEW_PATH"/market/priceoverview/"price path
MAX_MONEY_UNITS1.0e15largest amount parseMoneyCents scales

MarketPrice

FieldMeaning
found as boolthe market had a price
lowestPrice as stringcheapest listing, as Steam formatted it
medianPrice as stringmedian recent sale, as Steam formatted it
lowestCents as intlowestPrice in minor units
medianCents as intmedianPrice in minor units
volume as intsold in the last 24 hours, 0 when Steam omits it

Workshop (ISteamRemoteStorage)

Keyless. Both lookups are form POSTs with indexed publishedfileids[N] fields; Steam answers nothing else here.

FunctionReturnsNotes
publishedFileDetails(c, publishedFileIds)list of PublishedFile1 to 100 numeric ids; unknown items left out
publishedFile(c, publishedFileId)PublishedFilethrows when there is no such item
collectionDetails(c, collectionIds)list of Collection1 to 100 numeric ids; one entry per id, in order
collectionItems(c, collectionId)list of stringmember ids in collection order; throws when there is no such collection
workshopUrl(publishedFileId)stringhttps://steamcommunity.com/sharedfiles/filedetails/?id=<id>
workshopBrowseUrl(appId)stringhttps://store.steampowered.com/app/<id>/workshop/
workshopVisibilityName(visibility)string"public", "friends only", "private", "unlisted"; "unknown" otherwise
ConstantValueMeaning
WORKSHOP_PUBLIC0anyone
WORKSHOP_FRIENDS1the author's friends
WORKSHOP_PRIVATE2the author
WORKSHOP_UNLISTED3by direct link, not listed
WORKSHOP_BATCH100largest batch per request

PublishedFile

FieldMeaning
publishedFileId as stringid, the number in the Workshop URL
creator as stringauthor's id64
creatorAppId as intapp it was authored in
consumerAppId as intapp it is played in
title as stringtitle
description as stringBBCode
filename as stringstored file name
fileSize as intbytes
fileUrl as stringdirect download, "" for most items
previewUrl as stringpreview image URL
timeCreated as intUnix time published
timeUpdated as intUnix time updated
visibility as inta WORKSHOP_* value
banned as boolbanned by Valve
banReason as string"" when not banned
subscriptions as intcurrent subscribers
favorited as intcurrent favourites
lifetimeSubscriptions as intsubscribers ever
lifetimeFavorited as intfavourites ever
views as intpage views
tags as list of stringWorkshop tags

CollectionItem

FieldMeaning
publishedFileId as stringmember id
sortOrder as intposition
fileType as intSteam's file-type code

Collection

FieldMeaning
publishedFileId as stringthe collection's id
found as boolSteam had it
items as list of CollectionItemmembers in order

Econ (IEconService, ISteamEconomy)

The trade calls read the key owner's own offers; there is no steamid parameter. Accepting and declining are not offered: they need the mobile confirmation flow.

FunctionReturnsNotes
tradeOffersSummary(c, timeCutoff)TradeOffersSummarycounts only; timeCutoff 0 counts everything; throws when negative
tradeOffers(c, getSent, getReceived, activeOnly)TradeOffersthrows when both directions are false
tradeOffer(c, tradeOfferId)TradeOfferthrows on a non-numeric id or an offer the key cannot see
assetPrices(c, appId)list of AssetPricethrows when the game has no item store
tradeOfferStateName(state)stringstates 1-11, "unknown" otherwise
isPendingOffer(offer)boolactive (2) or awaiting confirmation (9)
isOneSided(offer)boolone side is empty
ConstantValueMeaning
TRADE_ACTIVE2waiting for the other side
TRADE_ACCEPTED3items exchanged
TRADE_CANCELED6withdrawn by the sender
TRADE_DECLINED7turned down by the recipient
TRADE_IN_ESCROW11accepted, items in escrow

TradeAsset

FieldMeaning
appId as intgame
contextId as stringinventory context
assetId as stringinventory id
classId as stringitem class
instanceId as stringitem instance
amount as intcount, for a stackable item
missing as boolleft the inventory since the offer; accepting fails

TradeOffer

FieldMeaning
tradeOfferId as stringid
otherSteamId as stringother party's id64, widened from the 32-bit id Steam sends
message as stringnote
state as inta TRADE_* value or another state 1-11
isOurOffer as boolthe key's account made it
timeCreated as intUnix time made
timeUpdated as intUnix time last changed
expirationTime as intUnix time it lapses
escrowEndDate as intUnix time escrow lifts, 0 when none
toGive as list of TradeAssetwhat the key's account hands over
toReceive as list of TradeAssetwhat it gets

TradeOffers

FieldMeaning
sent as list of TradeOffermade by the account
received as list of TradeOffermade to the account

TradeOffersSummary

FieldMeaning
pendingReceived as intincoming, awaiting an answer
newReceived as intincoming since the cutoff
updatedReceived as intincoming changed since the cutoff
pendingSent as intoutgoing, awaiting an answer
newlyAcceptedSent as intoutgoing accepted since the cutoff
updatedSent as intoutgoing changed since the cutoff
escrowReceived as intincoming in escrow
escrowSent as intoutgoing in escrow

AssetPrice

FieldMeaning
classId as stringitem class
name as stringthe store's internal name
date as stringdate added, "" when none
prices as map of string to intminor units per ISO code; only the codes Valve priced

Servers (IGameServersService)

FunctionReturnsNotes
gameServerAccounts(c)list of GameServerAccountthe key owner's accounts, login tokens included
gameServerInfo(c, steamId)GameServerInfopublic record of any server account
queryLoginToken(c, loginToken)LoginTokenStatusthrows on a blank token
isUsableServerAccount(account)boolneither deleted nor expired

GameServerAccount

FieldMeaning
steamId as stringserver's id64
appId as intgame
loginToken as stringsecret, treat as a password
memo as stringnote
deleted as booldeleted
expired as booltoken expired through disuse
lastLogon as intUnix time of the last login

GameServerInfo

FieldMeaning
steamId as stringserver's id64
appId as intgame, 0 when unknown

LoginTokenStatus

FieldMeaning
steamId as stringowning server account
banned as boolbanned from listing
expires as intUnix time it stops working, 0 when it does not

Errors

Messages name the fix or the cause:

  • validation: the app id must be positive, got 0
  • transport: GET https://store.steampowered.com/api/appdetails failed: ... (the URL never carries the query string, so never the key)
  • refusal: the storefront has no record of app 1 in country US - it may be delisted, region-locked, or not an app at all

A non-2xx GET reads ... failed: rest.getJson: HTTP <status>: <body>. A non-2xx POST names the usual cause: 400 rejected parameters, 401 missing or invalid key, 403 key not allowed to read the profile, 404 no such method or object, 429 rate limited, 500/502/503 Steam trouble.

jennifer
try {
    def d as steam.AppDetails init steam.appDetails($c, $appId);
} catch (e) {
    io.eprintf("%s\n", $e.message);
}

Costs

  • One connection per request. rest keeps no keep-alive session, so appPrices, appDetailsMany and appList pay a TLS handshake per id or page.
  • Bodies are capped at MAX_RESPONSE_BYTES (32 MiB).
  • plainText is linear in the body length, also on adversarial input (loose brackets, repeated image markers), so it is safe on user-written Workshop descriptions.

Requirements

  • Jennifer 0.25.0 or newer, the default jennifer binary: requests go through rest and http to net, which jennifer-tiny stubs out. The pure helpers work on both.
  • Standard library strings, lists, convert, math, json, io, os; bundled modules rest, http, uri. No other deck.

Tests run offline: jennifer test src/steam_test.j. Anchor a filter to ^test (--filter='^testParseMoney'); the refusal helpers are top-level functions that throw by design.