Inventory, DLC, and purchases
Read ownership and manage Steam inventory and purchase results.
Use your game’s Steam App ID. Publish its inventory item definitions and configure DLC in Steamworks before testing with an account that owns the relevant content.
Read inventory
Bind On Steam Inventory Result Ready on the SIK Inventory Subsystem, then request inventory. Match the returned handle to the handle in the callback. Read items only after a successful result and destroy the handle when finished. Create InventoryHandle (SIK Steam Inventory Result) and InventoryPending (Boolean, false). The example allows one request at a time; call StopInventoryQuery when its owner stops.
Loading the interactive viewer.
Game module dependency: SteamIntegrationKit.
Put this component in SteamInventoryExample.h and attach it to an actor. Items holds the returned items; LastStatus reports completion.
#pragma once
#include "Components/ActorComponent.h"
#include "Engine/GameInstance.h"
#include "Engine/World.h"
#include "Nodes/Inventory/SIK_InventoryLibrary.h"
#include "Nodes/Inventory/SIK_InventorySubsystem.h"
#include "SteamInventoryExample.generated.h"
UCLASS(ClassGroup = (Online), meta = (BlueprintSpawnableComponent))
class USteamInventoryExample : public UActorComponent
{
GENERATED_BODY()
public:
TArray<FSIK_SteamItemDetails> Items;
TEnumAsByte<ESIK_Result> LastStatus = ResultFail;
bool Refresh()
{
if (bPending || !GetWorld())
return false;
auto *GameInstance = GetWorld()->GetGameInstance();
auto *Inventory =
GameInstance ? GameInstance->GetSubsystem<USIK_InventorySubsystem>() : nullptr;
if (!Inventory)
return false;
Subsystem = Inventory;
Inventory->OnSteamInventoryResultReady.AddUniqueDynamic(this, &ThisClass::OnResult);
bPending = USIK_InventoryLibrary::GetAllItems(Handle);
if (!bPending)
{
LastStatus = ResultFail;
Stop();
}
return bPending;
}
void Stop()
{
if (bPending)
USIK_InventoryLibrary::DestroyResult(Handle);
bPending = false;
if (auto *Inventory = Subsystem.Get())
Inventory->OnSteamInventoryResultReady.RemoveDynamic(this, &ThisClass::OnResult);
}
protected:
virtual void EndPlay(const EEndPlayReason::Type Reason) override
{
Stop();
Super::EndPlay(Reason);
}
private:
bool bPending = false;
FSIK_SteamInventoryResult Handle;
TWeakObjectPtr<USIK_InventorySubsystem> Subsystem;
UFUNCTION()
void OnResult(FSIK_SteamInventoryResult Result, TEnumAsByte<ESIK_Result> Status)
{
if (!bPending || Result.Result != Handle.Result)
return;
LastStatus = Status;
Items.Reset();
if (Status == ResultOK && !USIK_InventoryLibrary::GetResultItems(Handle, Items))
LastStatus = ResultFail;
Stop();
}
};The callback ignores other requests. Stop() releases an active handle and removes this listener; call it when cancelling.
Get All Items returning true means the request started. On Steam Inventory Full Update is an additional freshness notification; it can be absent when inventory has not changed, so do not use it as your only completion signal.
Item definitions describe item types; item instances are the player’s owned stacks. Call Load SIK Item Definitions, wait for On Steam Inventory Definition Update, then use Get Item Definition IDs and Get SIK Item Definition Property for names, descriptions, and other metadata. The C++ methods have the same names on USIK_InventoryLibrary.
Buy inventory items
Read a selected item price
Loading the interactive viewer.
Start checkout for one item
Loading the interactive viewer.
#include "Nodes/Inventory/SIK_StartPurchase_AsyncFunction.h"
#include "Nodes/Inventory/SIK_RequestPrices_AsyncFunction.h"
#include "Nodes/Inventory/SIK_InventoryLibrary.h"
bool RequestStorePrices(const FScriptDelegate &OnReady, const FScriptDelegate &OnFailed)
{
auto *Request = USIK_RequestPrices_AsyncFunction::RequestPrices();
if (!Request)
return false;
Request->OnSuccess.Add(OnReady);
Request->OnFailure.Add(OnFailed);
Request->Activate();
return true;
}
bool ReadSelectedItemPrice(FSIK_SteamItemDef Item, int64 &CurrentPrice, int64 &BasePrice)
{
CurrentPrice = 0;
BasePrice = 0;
return USIK_InventoryLibrary::GetItemPrice(Item, CurrentPrice, BasePrice);
}
bool BuyOneSelectedItem(FSIK_SteamItemDef Item, const FScriptDelegate &OnStarted,
const FScriptDelegate &OnFailed)
{
auto *Request = USIK_StartPurchase_AsyncFunction::StartPurchase({Item}, {1});
if (!Request)
return false;
Request->OnSuccess.Add(OnStarted);
Request->OnFailure.Add(OnFailed);
Request->Activate();
return true;
}Price handlers take (TEnumAsByte<ESIK_Result>, const FString& CurrencyCode). Read the selected item price only from the successful price callback. Checkout handlers take (TEnumAsByte<ESIK_Result>, int64 OrderId, int64 TransactionId). Both nodes route Steam errors to OnFailure.
Use an item definition published for sale. Request prices before reading them and retain the returned currency code. The example prints raw price values; format them for your store UI. Steam pricing API. Supply one positive quantity per item definition. Start SIK Purchase starts checkout; its success is not permission to grant items yourself. After checkout, use Read inventory to observe delivered items; delivery may not be visible immediately. Keep the purchase event on an explicit Buy action, separate from loading prices. Handle cancellation without changing ownership.
Check DLC
Loading the interactive viewer.
#include "Nodes/Apps/SIK_AppLibrary.h"
bool CanUseSteamDlc(int32 DlcAppId)
{
return USIK_AppLibrary::IsDLCInstalled(DlcAppId);
}
void InstallOwnedDlc(int32 DlcAppId)
{
if (!CanUseSteamDlc(DlcAppId))
USIK_AppLibrary::InstallDLC(FSIK_AppId(DlcAppId));
}
bool ReadDlcDownload(int32 DlcAppId, int64 &Downloaded, int64 &Total)
{
Downloaded = 0;
Total = 0;
if (CanUseSteamDlc(DlcAppId))
return false;
const bool Available =
USIK_AppLibrary::GetDLCDownloadProgress(FSIK_AppId(DlcAppId), Downloaded, Total);
if (!Available)
{
Downloaded = 0;
Total = 0;
}
return Available;
}Call CanUseSteamDlc first on each refresh, then ReadDlcDownload if it is still unavailable. False from the progress query means no usable progress—not a completed install.
Call the refresh event from a timer or your download UI. Use your DLC’s App ID, not the base game’s. Is SIK DLC Installed checks both ownership and installation. Is SIK Subscribed App checks access to an app, which is a different question. A visible DLC store page is not proof of ownership, and owning DLC does not load its assets into Unreal for you.
Consumption, exchanges, and trusted ownership
Consume SIK Item, Exchange SIK Items, and Transfer SIK Item Quantity return inventory-result handles too: use the same completion and cleanup flow. Consuming an instance reduces its quantity and may remove it. Exchanges must match recipes configured in Steamworks; client calls cannot invent arbitrary rewards.
For inventory sent by another player, deserialize the signed result, check its completion status and freshness, then call Check SIK Result Steam ID against the authenticated player. A readable item array alone is insufficient. Destroy that result handle as well. See Valve’s inventory result requirements.
Keep publisher keys and privileged inventory grants on your backend. Validate ownership there for backend-controlled rewards; do not trust client-supplied item IDs or booleans.