Skip to main content

Game info, versions and platforms

Everything the SDK does is scoped to one game. The game id and API key you set at initialization decide which catalog you read, which capabilities are switched on, and which version taxonomy your mod filters are validated against. This page covers the read APIs on ICFCoreApi that report what the backend believes about your game, plus platforms and utilities, in cfcore-sdk-ue.

info

Initialize the SDK first. In C++, every sub-interface accessor on ICFCore except Utils() returns nullptr until initialization succeeds, so calling through one early is a null dereference. Null-check the accessor, do not just check ICFCore::IsInitialized. In Blueprint, UCFCoreSubsystem guards every node and fires its error pin with an FCFCoreError whose code is ECFCoreErrorCodes::FailedToInitialize. Every callback is marshalled back to the game thread.

Settings that scope every call on this page

Field on FCFCoreSettingsTypeEffect
gameIdint64Formatted into the request path (/v1/games/{gameId}). The only thing scoping GetGame, GetVersionTypes, GetVersions and GetVersionsDetailed. Must be greater than zero, or initialization fails with MissingGameId before any network request.
apiKeyFStringSent as an API key header when non empty. Must be non-empty, or initialization fails with MissingApiKey before any network request.
providerECFCoreExternalAuthProviderStore or platform provider. Values: None, Steam, PSN, XBL, WB, Epic, GOG. WB is Warner Brothers.
isServerboolSet true on a dedicated server build so the reported platform string becomes its _server variant, and adds a mod-server-request header. Also gates the server-only query behavior described below.
isServerPcOnlyboolRelevant only when isServer is true. Feeds filterPcOnly on the server's mod query: true returns the latest server mod that has a corresponding Windows mod, false returns one that has all supported platforms.
note

Get both gameId and apiKey from your game record in the Developer Portal at console.curseforge.com.

warning

No read API reports which platform string your build sent, so if a server build matches the wrong files, check isServer first.

note

Two query behaviours take effect only when isServer is true: devModIds, which requests unpublished mod revisions for testing, and filterPcOnly, which isServerPcOnly feeds.

Blueprint: build the struct with Make Settings From Project Config (which reads Edit > Project Settings > Plugins > CFCore) or Make Settings for inline values, both on UCFCoreBPLibrary. isServer is on that settings page, so a server target can set it without code. Your game id and API key come from the Developer Portal at console.curseforge.com, see Setting up your game.

The game model

ICFCoreApi::GetGame takes one FGetGameDelegate and no filter.

Field on FGameTypeMeaning
idint64The CurseForge game id. Matches your gameId.
nameFStringDisplay name.
slugFStringURL safe short name used in CurseForge web paths.
dateModifiedFDateTimeWhen the game record was last modified.
assetsFGameAssetsIcon, tile and cover art URLs.
statusECFCoreStatusLifecycle state of the game record.
apiStatusECFCoreApiStatusWhether the game is publicly visible through the API.
supportedFeaturesFGameSupportedFeaturesCapability flags enabled for this game.

FGame has no platform field and no version list. FGameAssets is three FString URLs with no defaults, so any can arrive empty and no SDK API fetches or caches them: iconUrl (small square icon), tileUrl (card or grid art), coverUrl (wide hero art).

ECFCoreStatusNumericECFCoreApiStatusNumeric
None0None0
Draft1Private1
Test2Public2
PendingReview3
Rejected4
Approved5
Live6
warning

During pre-launch integration your game record will usually not be Live or Public, so treat both as diagnostics for an internal debug overlay, not as gates in shipping code. See Testing and launching your game.

How it works

  1. Initialize the SDK and wait for the callback.
  2. Call the get game API. In C++ one delegate carries both the game and the error, in Blueprint they are two pins.
  3. Read supportedFeatures first if you branch on capability, then the presentation fields.
  4. Cache for the session. There is no change event for the game record.
#include <cfcore_context.h>
#include <api/cfcore_api.h>
#include <api/models/game.h>

void AMyModsMenu::QueryGameInfo() {
cfcore::ICFCoreApi* api = cfcore::CFCoreContext::GetInstance()->Api();
if (api == nullptr) {
return; // Api() is nullptr until Initialize succeeds.
}
api->GetGame(
cfcore::ICFCoreApi::FGetGameDelegate::CreateLambda(
[](TOptional<FGame> opt_game,
const TOptional<FCFCoreApiResponseError>& opt_err) {
if (opt_err.IsSet()) {
UE_LOG(LogTemp, Error, TEXT("GetGame failed (%d, unreachable %d)"),
opt_err->errorCode, opt_err->serverUnreachable ? 1 : 0);
return;
}
if (!opt_game.IsSet()) { return; }
const FGame& game = opt_game.GetValue();
const bool subs = game.supportedFeatures.supportModSubscriptions;
// game.name, game.slug, game.assets.coverUrl for your header UI.
}));
}

Blueprint: Get Game Info on CFCoreSubsystem, under cfcore|Api. Pins are on_game (a game output of type FGame) and on_error (an error output of type FCFCoreError, fields isError, code, apiError, description).

note

FCFCoreApiResponseError carries classifier booleans past errorCode and description, and they are how you decide whether to retry: cancelled, badRequest, entityNotFound, serverUnreachable, missingPrivileges, tokenExpired, resourceExpired, failedToParseServerResponse.

Supported features: what the backend has enabled for your game

FGameSupportedFeatures is the runtime answer to which optional capabilities are switched on for your game id.

FieldTypeDefaultWhat it gates
supportModSubscriptionsboolfalseThe whole ICFCore::Subscription surface, configured by FCFCoreSettingsSubscriptions

That is the complete set of flags in the current release. The subscription surface it gates is EnableAutoManagement, DisableAutoManagement, Subscribe, Unsubscribe, GetModsSubscriptions, SyncSubscriptions, GetSyncPlan and ExecuteSyncPlan. One flag. Use it as the visibility condition for your subscription UI: when it is false, do not render a subscribe button and do not call EnableAutoManagement, since those calls fail with HTTP errors when subscriptions are not enabled for the game. If it is false and you expected true, ask cfforstudios@overwolf.com to enable subscriptions for your game id.

warning

The flag says the capability is enabled for the game, not that the player is authenticated. There is a separate ECFCoreErrorCodes::UserNotAuthenticated, and auto-subscribe runs on the first login after initialization, so gate the UI on the flag and the action on authentication state. Concepts are in Authentication overview.

Blueprint: break supportedFeatures out of FGame, feed supportModSubscriptions into a Branch and drive widget visibility from it. The subscription nodes sit under cfcore|Subscription.

Game version types and versions

A version type is a branch or release line of your game, configured per game in the Developer Portal at console.curseforge.com. Its numeric id is what you put into a mod search filter, so read the taxonomy at runtime and your filter UI stays correct when a branch is added.

Three calls, each taking one delegate and no filter:

MethodEndpointDelivers
GetVersionTypes/v1/games/{gameId}/version-typesTOptional<TArray<FGameVersionType>>
GetVersions/v1/games/{gameId}/versionsTOptional<TArray<FGameVersionsByType>>, versions as strings
GetVersionsDetailed/v2/games/{gameId}/versionsconst TOptional<TArray<FGameVersionsDetailedByType>>&, versions as objects with ids
ModelFieldTypeMeaning
FGameVersionTypeidint64The version type id. Used as gameVersionTypeId in filters and on file models.
gameIdint64The game this version type belongs to.
nameFStringDisplay name for a dropdown label.
slugFStringURL safe short name.
FGameVersionsByTypetypeint64The version type id. Join against FGameVersionType.id.
versionsTArray<FString>Version strings in that type, the values you pass as gameVersion.
FGameVersionsDetailedByTypetypeint64The version type id.
versionsTArray<FGameVersionDetailed>The versions in that type, as objects.
FGameVersionDetailedidint64Numeric id of the individual game version.
nameFStringDisplay name.
slugFStringURL safe short name.
warning

FGameVersionsByType.type is an id, not a name, and that model has no name field. To label the group, call GetVersionTypes as well and join on id.

Which to use. GetVersions when you only need strings for a search filter, because FCFCoreSearchModsFilter.gameVersion is an FString. GetVersionsDetailed when you need the numeric version id, and the concrete reason is the upload path: FCreateModFileRequest.gameVersionIds is a TArray<int64>, so declaring which game versions a mod file supports means sending FGameVersionDetailed.id values. See Cloud cooking upload flows.

note

FGetVersionsDetailedDelegate declares its array parameter as a const reference, where the other two take theirs by value. Match the declaration or the lambda will not bind.

How it works

  1. Call the version types API and the versions API once after initialization.
  2. Join the arrays: FGameVersionsByType.type equals FGameVersionType.id.
  3. Render a two-level filter, version type as the group and version string as the entry. The shipped mod browser does this for you.
  4. A selected version string goes into the search filter as gameVersion, a selected group as gameVersionTypeId.
api->GetVersionTypes(
cfcore::ICFCoreApi::FGetVersionTypesDelegate::CreateLambda(
[](TOptional<TArray<FGameVersionType>> opt_types,
const TOptional<FCFCoreApiResponseError>& opt_err) {
if (opt_err.IsSet() || !opt_types.IsSet()) { return; }
for (const FGameVersionType& type : opt_types.GetValue()) {
// type.id keys the dropdown entry, type.name labels it.
}
}));
// GetVersions has the same shape: FGameVersionsByType.type joins back to
// an FGameVersionType.id, and .versions holds the strings.

Blueprint: Get Version Types Info and Get Versions Info on CFCoreSubsystem, under cfcore|Api. Each has an on_results pin (a version_types or versions array) and an on_error pin carrying an FCFCoreError. The SDK exposes no Blueprint node for GetVersionsDetailed. Both detailed structs are BlueprintType with BlueprintReadOnly fields, so a Blueprint-only project can close the gap with a C++ wrapper UFUNCTION that null-checks Api(), calls GetVersionsDetailed and forwards the array through a dynamic delegate. Request parity through cfforstudios@overwolf.com, naming GetVersionsDetailed.

Using a version type id when filtering mods

The version type id is the join key between the version taxonomy and the mod catalog. It appears in one filter and on two read models.

WhereFieldTypeDirection
FCFCoreSearchModsFiltergameVersionTypeIdint32You set it. Restricts results to mods with a file in that version type.
FFileIndex (on FCFCoreMod.latestFilesIndexes)gameVersionTypeIdint32You read it. Which version type each indexed latest file belongs to.
FSortableGameVersion (on FFile.sortableGameVersions)gameVersionTypeIdint32You read it. Which version type each declared game version of a file belongs to.
warning

FGameVersionType.id and FGameVersionsByType.type are int64, but all three gameVersionTypeId fields are int32. Narrow explicitly, and do not round-trip the value through a float in Blueprint. A filter field set to 0, an empty string, or an enum None means "no constraint", so a gameVersionTypeId of 0 does not filter.

FCFCoreSearchModsFilter filter;
filter.gameVersionTypeId = static_cast<int32>(SelectedVersionTypeId);
filter.sortField = ECFCoreModsSearchSortField::Popularity;
filter.sortOrder = ECFCoreSortOrder::Desc;

FCFCoreApiRequestPagination pagination; // index 0, pageSize 20 by default.
api->SearchMods(filter, pagination, MySearchDelegate);

Blueprint: build the filter with Unreal's auto-generated make-struct node for FCFCoreSearchModsFilter, set its gameVersionTypeId pin from the id captured out of Get Version Types Info, add Make Api Request Pagination (on UCFCoreBPLibrary) for a page other than the first, then connect both into Search Mods Info.

Platform support

Platform matters in three separate places, and conflating them is the most common way to reach a wrong conclusion about whether a target is supported: the string your build reports, the enum that declares what a cooked file was built for, and the matching a client does when joining a server.

The platform your build reports

The value the backend resolves against is a lowercase string, not ECFCorePlatform. It is chosen at compile time from Unreal's platform macros during SDK bootstrap and sent on every request as the x-platform header. When isServer is true the SDK appends _server.

Unreal platform macroReported string
PLATFORM_WINDOWSwindows
PLATFORM_WINGDKwindows_gdk
PLATFORM_XBOXONExbox_one
PLATFORM_XSXxbox_xsx, or xbox_xss when the console reports as Series S
PLATFORM_PS4ps4
PLATFORM_PS5ps5
PLATFORM_MACmac
PLATFORM_IOSios
PLATFORM_TVOStvos
PLATFORM_ANDROIDandroid
PLATFORM_SWITCHswitch
PLATFORM_HOLOLENShololens
PLATFORM_LINUXlinux
warning

This resolution lives in private bootstrap code, so you cannot read the value your build reports from C++ or Blueprint, and there is no platform field on FGame. The selection is a chain of compile-time macro tests with no fallback branch: if you are porting to a target that is not listed, do not assume it degrades to windows. Confirm it with cfforstudios@overwolf.com, naming the Unreal platform macro your build defines.

The platform enum in source

ECFCorePlatform is a uint8 backed BlueprintType enum. These are the values in the current release, in declaration order.

ValueNumericValueNumeric
None0Mac7
Windows1IOS8
XboxOne2TVOS9
XboxXS3Android10
Linux4Switch11
PS45WindowsServer12
PS56LinuxServer13
warning

This enum is not the request-path vocabulary. The only public struct carrying an ECFCorePlatform value in the current release is FCreateCookedModFileRequest.platform, which platform a manually cooked file was built for, on a struct used for manual cooking. It appears nowhere in the request pipeline. The enum answers what you declare a cooked artifact to be, the header string answers what your build is, and the two do not line up.

Mismatch with the published platform list

The Unreal overview page states platform support as Windows, PlayStation 4, PlayStation 5, Xbox, Windows (GDK), and Nintendo Switch. That list is narrower than either SDK vocabulary, and one entry on it has no enum member. Both facts are stated here rather than reconciled.

Published entryReported stringEnum member
Windowswindows, plus windows_server when isServerWindows (1), WindowsServer (12)
PlayStation 4ps4PS4 (5)
PlayStation 5ps5PS5 (6)
Xboxxbox_one, xbox_xsx, xbox_xssXboxOne (2), XboxXS (3)
Windows (GDK)windows_gdknone. There is no WindowsGDK member, which matters only on the manual cooking path.
Nintendo SwitchswitchSwitch (11)
not publishedlinux, linux_server, mac, ios, tvos, android, hololensLinux (4), Mac (7), IOS (8), TVOS (9), Android (10), LinuxServer (13)
warning

Presence in either vocabulary is not a statement that the platform is supported for your integration, and neither reflects a commercial or certification agreement. Treat the published list as authoritative for what is supported today, and confirm the platform set for your title with cfforstudios@overwolf.com before planning a port, naming the target and your game id. Console requirements are in Xbox and PlayStation compliance.

Matching files to the client's platform

Because the platform travels in a header, you never pass it. ICFCoreApi::MatchPlatformFiles takes an array of file ids and returns the FFile objects matching those ids for the current platform. Its filter, FMatchPlatformFilesFilter, has one field, fileIds (TArray<int64>). The implementation POSTs to /v1/mods/files/match-platform, where the backend reads the x-platform header. The intended use is client-server sessions: the server returns file ids, the client downloads the files matching its platform.

FMatchPlatformFilesFilter filter;
filter.fileIds = InFileIds;

// Both delegate parameters are by value here, unlike every other method
// on this interface. Copying the GetGame signature will not compile.
api->MatchPlatformFiles(
filter,
cfcore::ICFCoreApi::FMatchPlatformFilesDelegate::CreateLambda(
[](TOptional<TArray<FFile>> opt_files,
TOptional<FCFCoreApiResponseError> opt_err) {
if (opt_err.IsSet() || !opt_files.IsSet()) { return; }
for (const FFile& file : opt_files.GetValue()) { /* file.id */ }
}));

Blueprint: Match Platform Files By Ids on CFCoreSubsystem, under cfcore|Api. Pass an FMatchPlatformFilesFilter with fileIds populated. Results arrive on OnResults as a files array (same delegate type as Get Files Info By Ids), failures on OnError.

note

When nothing in the list matches, the client-server library path surfaces ECFCoreErrorCodes::NoPlatformFilesMatched. Handle it as a joinability failure with a player-facing message, not a transport error to retry. That code comes from the client-server flow, not from MatchPlatformFiles itself.

Diagnostic read APIs

MethodEndpointReturnsStudio-facing
GetActiveCookingVersion/v1/cooking/sdk-versionFSDKVersion, one field: build (int32)Yes
GetDirectDownloadDomain/v2/mod-files/direct-download-domainFStringNo, SDK internal
GetDirectDownloadDomainEx/v3/mod-files/direct-download-domainFDirectDownloadDomainEx, one field: domain (FString)No, SDK internal

GetActiveCookingVersion is the only one of the three you call. build is the build number of the cloud cooker running for your game. Cooked mod files load only on a compatible engine build, so log it alongside a cooking failure and compare it when a mod that cooked last week stops loading after an engine upgrade. See Cloud cooking. Its delegate declares the first parameter as const TOptional<FSDKVersion>, by value with a top-level const, unlike most others on this interface.

warning

Both domain calls exist for chunked downloading and are not meant to be called from your game. Do not call them and do not build download URLs by hand, use the library install path. They are listed here only so you recognise them in a network capture. See also Browsing and discovery, which names the same two. If you need to know which host must be reachable behind a corporate or console allowlist, ask cfforstudios@overwolf.com rather than reading it out of the SDK, and include your game id and target platform.

Blueprint: the SDK exposes no Blueprint node for any of these three. For the download domains that matches their internal marking. For the cooking version, FSDKVersion is a BlueprintType struct with a BlueprintReadOnly build field, so a C++ wrapper UFUNCTION closes the gap.

Utils and the compression service

ICFCore::Utils() returns an ICFCoreUtils*, which exposes one thing: Compression(), returning an ICompressionService*. This is the SDK's own zip implementation, exposed so mod tooling inside your title does not need a second compression dependency: packaging authored content into a zip before uploading it as a mod file revision, and unpacking a zip your own tooling produced.

This branch needs no initialization. Utils() returns a valid pointer unconditionally, Compression() never returns nullptr, and Zip Paths is the only Blueprint node in the plugin with no initialization guard, so build-time and editor tooling can compress without bringing the SDK up.

MethodParametersReturns
Zipconst TSharedRef<TArray<FString>> files_to_zip, const FString& output_zip_file, FProgressDelegate on_progressTFuture<ECompressionError>
Unzipconst FString& zip_file, const FString& output_folder, FProgressDelegate on_progressTFuture<ECompressionError>

files_to_zip may contain directories: a file path is taken as is, a directory is expanded recursively, entry names are made relative to the common root of the resolved inputs, and output_zip_file is removed if it appears in the list. Hand it a mod folder rather than enumerating files. It takes a TSharedRef because the call captures that reference into a thread-pool task and returns immediately, so build it with MakeShared<TArray<FString>> and do not mutate it afterwards.

FProgressDelegate delivers an FCompressionProgress:

FieldTypeMeaning
progressint32Percentage of files processed, files done over total files. Not a byte percentage.
fileFStringThe file being processed. On zip the absolute source path, on unzip the entry name inside the archive.

Progress fires only when the integer percentage changes, so consecutive small files can produce no callback. The value is seeded at -1 so a first callback at 0 is still delivered, and it is marshalled to the game thread, so you can drive UMG from it directly.

ECompressionErrorNumericMeaning
None0Success.
FailedToReadZip1The archive could not be opened for reading (unzip).
FailedToExtractFile2A file could not be extracted. The SDK log carries the detail.
FailedToWriteFile3A file could not be written to the output location, or the output archive could not be created (zip).
warning

None is the success value, so compare against None rather than testing a boolean. None is also not proof an archive was produced: an empty input list completes with None after logging that there were no input files to zip, and an input list that resolves to no files completes with None after logging that zipping failed because no files were found. Check the output file after the future completes.

How it works

  1. Get the compression service from Utils(). No initialization needed.
  2. Build the input list as a shared array (zip) or point at an existing archive (unzip).
  3. Bind a progress delegate if you want a progress bar.
  4. Start the operation and keep the returned future. The work runs on a worker thread.
  5. Inspect the ECompressionError. The promise is fulfilled on the game thread, so a TFuture::Next continuation can touch UI directly.
#include <utils/cfcore_utils.h>
#include <utils/compression/compression_service.h>

void AMyModTools::PackageAuthoredContent(const TArray<FString>& InFiles,
const FString& InOutputZipFile) {
cfcore::ICompressionService* compression =
cfcore::CFCoreContext::GetInstance()->Utils()->Compression();

ZipFuture = compression->Zip(
MakeShared<TArray<FString>>(InFiles), InOutputZipFile,
cfcore::ICompressionService::FProgressDelegate::CreateLambda(
[](const FCompressionProgress& progress) {
UE_LOG(LogTemp, Display, TEXT("Zipping %s (%d%%)"),
*progress.file, progress.progress);
}))
.Next([InOutputZipFile](ECompressionError err) {
if (err != ECompressionError::None) {
UE_LOG(LogTemp, Error, TEXT("Zip failed with code %d"), (int32)err);
return;
}
if (!FPaths::FileExists(InOutputZipFile)) {
UE_LOG(LogTemp, Warning, TEXT("Zip succeeded, no archive at %s"),
*InOutputZipFile);
}
});
}

Blueprint: Zip Paths on CFCoreSubsystem, under cfcore|Utils|Compression. Pins are InPathsToZip (string array), InOutputZipFile (string), OnProgress (an FCompressionProgress output), OnSuccess (no payload) and OnError (an ECompressionError output), so you do not compare against None yourself. Unlike the API nodes it is declared without AutoCreateRefTerm, so no delegate pin is auto-created: wire at least OnSuccess and OnError.

note

The SDK exposes UtilsCompressionZipPaths (Zip Paths) but no unzip node, even though ICompressionService::Unzip exists in C++. A Blueprint-only project that needs to extract an archive needs a C++ wrapper UFUNCTION, or should rely on the library install path, which extracts mod archives for you. Request parity through cfforstudios@overwolf.com, naming ICompressionService::Unzip. An in-flight unzip cannot be cancelled in the current release. Do not offer a cancel button you cannot honour.