GS2-SerialKey SDK for Game Engine API Reference
Model
EzSerialKey
Serial Code
The serial code issued can be used only once. Serial codes are issued in the format “RPCLP-FP7N-NCDMJ-FLVA-IRI4” and the data length cannot be changed. Information on the type of campaign is also included within the serial code. When using the serial code, simply specify the namespace in which the serial code is to be used.
| Type | Condition | Required | Default | Value Limits | Description | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| campaignModelName | string | ✓ | ~ 128 chars | Campaign name The name of the campaign model this serial code belongs to. Campaign information is embedded within the serial code itself, so only the namespace needs to be specified when using the code. | ||||||||||
| metadata | string | ~ 2048 chars | Metadata Arbitrary values can be set in the metadata. Since they do not affect GS2’s behavior, they can be used to store information used in the game. | |||||||||||
| code | string | ✓ | ~ 48 chars | Serial Code The serial code string in the format “XXXXX-XXXX-XXXXX-XXXX-XXXX”. Each code is unique and includes campaign identification information. The code format and data length are fixed and cannot be changed. | ||||||||||
| status | String Enum enum { “ACTIVE”, “USED”, “INACTIVE” } | “ACTIVE” | Status The current usage status of this serial code. Transitions from ACTIVE to USED when consumed by a user. The transition is protected by optimistic locking to prevent double-use. INACTIVE codes cannot be used.
|
EzCampaignModel
Campaign Model
A Campaign Model is used to define and manage campaigns, linking them to serial codes.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| name | string | ✓ | ~ 128 chars | Campaign Model name | ||
| metadata | string | ~ 2048 chars | Metadata Arbitrary values can be set in the metadata. Since they do not affect GS2’s behavior, they can be used to store information used in the game. | |||
| enableCampaignCode | bool | false | Whether to allow redemption with campaign code When enabled, users can redeem rewards using a shared campaign code (the campaign name) instead of individual serial codes. This allows a single code to be used by multiple users. |
Methods
getCampaignModel
Get the details of a specific serial code campaign
Retrieves a single campaign model by name, including its configuration.
A campaign model defines a group of serial codes that share the same purpose and settings. For example, you might have separate campaigns for “Launch Bonus Codes”, “Magazine Promotion Codes”, or “Event Giveaway Codes”.
The response includes:
- Campaign name and metadata
- Whether the campaign is currently active and accepting code redemptions
Use this to check campaign details before displaying a code entry screen — for example, to verify the campaign is active before allowing players to enter a serial code.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| campaignModelName | string | ✓ | ~ 128 chars | Campaign Model name |
Result
| Type | Description | |
|---|---|---|
| item | EzCampaignModel | Campaign Model |
Implementation Example
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).CampaignModel(
campaignModelName: "1111campaign-0001"
);
var item = await domain.ModelAsync(); var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).CampaignModel(
campaignModelName: "1111campaign-0001"
);
var future = domain.ModelFuture();
yield return future;
var item = future.Result; const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->CampaignModel(
"1111campaign-0001" // campaignModelName
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}Value change event handling
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).CampaignModel(
campaignModelName: "1111campaign-0001"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).CampaignModel(
campaignModelName: "1111campaign-0001"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->CampaignModel(
"1111campaign-0001" // campaignModelName
);
// Start event handling
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::SerialKey::Model::FCampaignModel> value) {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
Domain->Unsubscribe(CallbackId);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
get
Look up a serial code’s status
Retrieves the details of a specific serial code, including whether it has been used and which campaign it belongs to.
Use this to check a code’s status before or after redemption — for example:
- Showing “This code has already been used” when a player enters a code that was already redeemed
- Displaying campaign information (what rewards the code gives) before the player confirms redemption
- Looking up a code for customer support purposes
The code should be in the format like “XXXXX-XXXX-XXXXX-XXXX-XXXXX”. The response includes the serial code details and the associated campaign model.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| code | string | ✓ | ~ 48 chars | Serial Code The serial code string in the format “XXXXX-XXXX-XXXXX-XXXX-XXXX”. Each code is unique and includes campaign identification information. The code format and data length are fixed and cannot be changed. |
Result
| Type | Description | |
|---|---|---|
| item | EzSerialKey | Serial Code |
| campaignModel | EzCampaignModel | Campaign Model |
Implementation Example
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).User(
userId: "user-0001"
).SerialKey(
serialKeyCode: "code-0001"
);
var item = await domain.ModelAsync(); var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).User(
userId: "user-0001"
).SerialKey(
serialKeyCode: "code-0001"
);
var future = domain.ModelFuture();
yield return future;
var item = future.Result; const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->User(
"user-0001" // userId
)->SerialKey(
"code-0001" // serialKeyCode
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}Value change event handling
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).User(
userId: "user-0001"
).SerialKey(
serialKeyCode: "code-0001"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).User(
userId: "user-0001"
).SerialKey(
serialKeyCode: "code-0001"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->User(
"user-0001" // userId
)->SerialKey(
"code-0001" // serialKeyCode
);
// Start event handling
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::SerialKey::Model::FSerialKey> value) {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
Domain->Unsubscribe(CallbackId);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
useSerialCode
Redeem a serial code
Uses (consumes) a serial code, marking it as redeemed by the current player. Once a code is used, it cannot be used again by anyone.
This is the main API for the “Enter Serial Code” feature in your game. The typical flow is:
- The player opens a “Redeem Code” screen in the game
- The player types in a serial code (e.g., from a promotional card, email, or website)
- Your game calls UseSerialCode with the entered code
- If successful, the code is marked as used — combine this with a reward distribution system to give the player their reward
- If the code was already used, a “already used” error is returned
- If the code doesn’t exist, a “code not found” error is returned
Common use cases:
- Promotional codes bundled with merchandise or magazines
- Gift codes distributed at events or through social media
- Pre-registration reward codes
- Partner collaboration codes
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| code | string | ✓ | ~ 48 chars | Serial Code The serial code string in the format “XXXXX-XXXX-XXXXX-XXXX-XXXX”. Each code is unique and includes campaign identification information. The code format and data length are fixed and cannot be changed. |
Result
| Type | Description | |
|---|---|---|
| item | EzSerialKey | Serial Code |
| campaignModel | EzCampaignModel | Campaign Model |
Error
Special exceptions are defined in this API. GS2-SDK for GameEngine provides specialized exceptions derived from general exceptions to facilitate handling of errors that may need to be handled in games. Please refer to the documentation here for more information on common error types and handling methods.
| Type | Base Type | Description |
|---|---|---|
| AlreadyUsedException | BadRequestException | The specified serial code has already been used. |
| CodeNotFoundException | NotFoundException | The specified serial code does not exist. |
Implementation Example
try {
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).SerialKey(
serialKeyCode: "code-0001"
);
var result = await domain.UseSerialCodeAsync(
code: "code-0001"
);
var item = await result.ModelAsync();
} catch(Gs2.Gs2SerialKey.Exception.AlreadyUsedException e) {
// The specified serial code has already been used.
} catch(Gs2.Gs2SerialKey.Exception.CodeNotFoundException e) {
// The specified serial code does not exist.
} var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).SerialKey(
serialKeyCode: "code-0001"
);
var future = domain.UseSerialCodeFuture(
code: "code-0001"
);
yield return future;
if (future.Error != null)
{
if (future.Error is Gs2.Gs2SerialKey.Exception.AlreadyUsedException)
{
// The specified serial code has already been used.
}
if (future.Error is Gs2.Gs2SerialKey.Exception.CodeNotFoundException)
{
// The specified serial code does not exist.
}
onError.Invoke(future.Error, null);
yield break;
}
var future2 = future.Result.ModelFuture();
yield return future2;
if (future2.Error != null)
{
onError.Invoke(future2.Error, null);
yield break;
}
var result = future2.Result; const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->SerialKey(
"code-0001" // serialKeyCode
);
const auto Future = Domain->UseSerialCode(
"code-0001" // code
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
auto e = Future->GetTask().Error();
if (e->IsChildOf(Gs2::SerialKey::Error::FAlreadyUsedError::Class))
{
// The specified serial code has already been used.
}
if (e->IsChildOf(Gs2::SerialKey::Error::FCodeNotFoundError::Class))
{
// The specified serial code does not exist.
}
return false;
}
// obtain changed values / result values
const auto Future2 = Future->GetTask().Result()->Model();
Future2->StartSynchronousTask();
if (Future2->GetTask().IsError())
{
return Future2->GetTask().Error();
}
const auto Result = Future2->GetTask().Result();