// SteamGPT API - TypeScript types for all responses | https://steamgpt.net // Conventions: optional (?) fields are ABSENT (undefined) when unknown; `| null` fields are always present. // Success: {result: "success", data: T}. Error: ErrorResponse. Switch on the `error` slug, not on message text. export type ErrorSlug = | 'player_not_found' // 404: id did not resolve or profile unknown to Steam | 'no_faceit_data' // 404: no FACEIT profile for this player | 'batch_too_large' // 400: more than 100 ids in /batch | 'batch_no_valid_ids' // 404: no valid steamid64 in /batch input | 'no_bans_data' // 404: Steam did not return ban data, retry later | 'bad_request' // 400: malformed body or unknown include value; 413: body over 16kb | 'unknown_endpoint' // 404: wrong path | 'invalid_token' // 401: optional Bearer boost-token invalid/expired - mint anew or omit Authorization | 'rate_limited' // 429: honor Retry-After header | 'internal'; // 500: retry later export interface ErrorResponse { result: 'error'; code: number; // HTTP status error: ErrorSlug; message: string; } export interface Ids { steamid64: string; // always present, 17 digits steamid: string | null; // STEAM_1:0:x; null only if conversion failed steamid3: string | null; // [U:1:x] } /** Raw Steam GetPlayerSummaries player object, field names unmodified. * Optional fields are ABSENT, not null, when Steam does not return them * (private profiles expose only the public subset). */ export interface SteamPlayer { steamid: string; personaname?: string; profileurl?: string; avatar?: string; avatarmedium?: string; avatarfull?: string; avatarhash?: string; personastate?: 0 | 1 | 2 | 3 | 4 | 5 | 6; // offline/online/busy/away/snooze/trade/play communityvisibilitystate?: number; // 3 = public profilestate?: number; commentpermission?: number; lastlogoff?: number; // unixtime timecreated?: number; // unixtime gameid?: string; gameextrainfo?: string; gameserverip?: string; primaryclanid?: string; loccountrycode?: string; locstatecode?: string; loccityid?: number; personastateflags?: number; [key: string]: unknown; // Steam may add fields } /** ok - data present; empty - source answered, player has no such data; * unavailable - source did not answer, an empty block is NOT evidence of absence; * excluded - block was not requested via include. */ export type SourceStatus = 'ok' | 'empty' | 'unavailable' | 'excluded'; export interface Canonical { steamid64: string; url: string; // stable URL: vanity and steamid64 inputs are the same resource } export interface SourceProvenance { source: string; // e.g. "Steam Web API", "FACEIT API" retrieved_at: number | null; // unixtime of the cached snapshot age_seconds: number | null; // snapshot age at response time fresh: boolean; // age within cache_ttl; false when unknown cache_ttl: number | null; // refresh policy in seconds refreshed_with?: string; // steam_bans only: bans refresh together with this source snapshot } export interface ProfileData { steamid64: string; ids: Ids; steam: SteamPlayer | null; // null when no data could be fetched canonical: Canonical; provenance: { steam: SourceProvenance }; } export interface ProfileResponse { result: 'success'; data: ProfileData; } export interface FriendFull { steamid64: string; steam: SteamPlayer; } export interface FriendMedium { steamid64: string; personaname: string | null; } export type FriendShort = string; // plain steamid64 export interface FriendsData { count: number; // total known friends, may exceed friends.length friends: TFriend[]; // element shape depends on ?detail: short | medium | full (default) } export interface FriendsResponse { result: 'success'; data: FriendsData; } /** FACEIT API player object; may be a reduced fallback (nickname/country/games only) * when the full object is not collected yet. */ export interface FaceitPlayer { player_id?: string; nickname?: string; avatar?: string; country?: string; steam_nickname?: string; memberships?: string[]; verified?: boolean; faceit_url?: string; // contains {lang} placeholder activated_at?: string; // ISO datetime games?: Record; [key: string]: unknown; } export interface FaceitData { steamid64: string; faceit: FaceitPlayer | null; // null when player is unknown to FACEIT bans: Array>; // [] when no known bans provenance: { faceit: SourceProvenance }; } export interface FaceitResponse { result: 'success'; data: FaceitData; } /** Blocks marked optional are ABSENT when excluded via ?include= / include argument. */ export interface SummaryData extends ProfileData { faceit?: FaceitPlayer | null; faceit_bans?: Array>; friends?: FriendsData; // capped by friends_limit (default 100) steam_bans?: SteamBans | null; // absent only when include excludes "bans" sources: { steam: SourceStatus; faceit: SourceStatus; friends: SourceStatus; bans: SourceStatus }; partial: boolean; // true when at least one source is unavailable provenance: { steam: SourceProvenance | null; faceit?: SourceProvenance | null; steam_bans?: SourceProvenance | null }; // keys follow include, like the data blocks } export interface SummaryResponse { result: 'success'; data: SummaryData; } /** Batch entries are leaner than /profile: no canonical/provenance, * and faceit / steam_bans appear only when requested via include. */ export interface BatchPlayer { steamid64: string; ids: Ids; steam: SteamPlayer | null; faceit?: FaceitPlayer | null; faceit_bans?: Array>; steam_bans?: SteamBans | null; } export interface BatchData { count: number; players: BatchPlayer[]; not_found: string[]; // valid steamid64 not found in cache invalid: string[]; // sanitized echo of non-steamid64 inputs } export interface BatchResponse { result: 'success'; data: BatchData; } /** Pure identifier resolver (/identity): no profile data. */ /** /converter/{id}: every representation of one account. */ export interface ConverterData { steamid64: string; // decimal, 17 digits steamid64_hex: string; // same number in hex, no prefix steamid: string; // STEAM_1:y:z (modern Source games) steamid_legacy: string; // STEAM_0:y:z - SAME account, legacy universe digit steamid3: string; // [U:1:x] accountid: number; // 32-bit account id steam_hex: string; // steam:hex form used by FiveM profile_url: string; input_format: 'steamid64' | 'steamid64_hex' | 'steamid' | 'steamid3' | 'steam_hex' | 'accountid' | 'profile_url'; converted: true; } export interface ConverterResponse { result: 'success'; data: ConverterData; } export interface IdentityData { steamid64: string; steamid: string | null; // STEAM_1:0:x steamid3: string | null; // [U:1:x] steam_hex: string | null; // steam:hex form used by FiveM vanity: string | null; // custom URL name when known, null otherwise profile_url: string; resolved: true; } export interface IdentityResponse { result: 'success'; data: IdentityData; } /** Raw Steam GetPlayerBans object. */ export interface SteamBans { SteamId: string; CommunityBanned: boolean; VACBanned: boolean; NumberOfVACBans: number; DaysSinceLastBan: number; NumberOfGameBans: number; EconomyBan: string; // 'none' | 'probation' | 'banned' } export interface BansData { steamid64: string; bans: SteamBans; provenance: { steam_bans: SourceProvenance }; } export interface BansResponse { result: 'success'; data: BansData; } /** /compare/{id1}/{id2}: both full summaries + shared friends. */ export interface CompareData { a: SummaryData; b: SummaryData; shared_friends: { count: number; friends: Array<{ steamid64: string; personaname: string | null }> }; } export interface CompareResponse { result: 'success'; data: CompareData; }