GS2-Inbox SDK for Game Engine API Reference
Model
EzMessage
Message
Message data delivered to a message box prepared for each game player.
Messages have an open state, and you can set an Acquire Action to be executed when opened. Messages can be set to expire, and messages that expire are automatically deleted regardless of whether they are unread or read after opening. Messages will be deleted even if you have not received the attached reward.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| messageId | string | * | ~ 1024 chars | Message GRN * Set automatically by the server | ||
| name | string | ✓ | UUID | ~ 36 chars | Message Name Maintains a unique name for each message. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each message. | |
| metadata | string | ✓ | ~ 4096 chars | Metadata Arbitrary data representing the message content, such as a JSON string containing the message title, body text, sender information, and display parameters. GS2 does not interpret this value; it is passed through to the game client for rendering the message UI. Maximum 4096 characters. | ||
| isRead | bool | false | Read Status Indicates whether the message has been opened by the user. When a message is opened, this flag is set to true, the readAcquireActions are executed to deliver attached rewards, and the readAt timestamp is recorded. If isAutomaticDeletingEnabled is set on the namespace, the message is deleted after being read. | |||
| readAcquireActions | List<EzAcquireAction> | [] | 0 ~ 100 items | Read Acquire Actions The list of acquire actions executed when the user opens this message. Used to attach rewards such as items, currency, or resources to messages. Multiple actions can be combined to grant different reward types simultaneously. Up to 100 actions per message. | ||
| receivedAt | long | * | Now | Datetime of creation Unix time, milliseconds * Set automatically by the server | ||
| readAt | long | 0 | Datetime of read Unix time, milliseconds | |||
| expiresAt | long | Datetime of ttl Unix time, milliseconds |
EzConfig
Configuration
Configuration values applied to transaction variables
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| key | string | ✓ | ~ 64 chars | Name | ||
| value | string | ~ 51200 chars | Value |
EzAcquireAction
Acquire Action
Represents a single acquire action attached to a message as a reward. Consists of an action type (e.g., add items to inventory, increase currency) and its request parameters. When a message is opened, these actions are assembled into transactions and executed to deliver the rewards to the user.
EzVerifyActionResult
Verify Action execution result
EzConsumeActionResult
Consume Action execution result
EzAcquireActionResult
Acquire Action execution result
EzTransactionResult
Transaction execution results
Result of a transaction executed using the server-side automatic transaction execution feature
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| transactionId | string | ✓ | 36 ~ 36 chars | Transaction ID | ||
| verifyResults | List<EzVerifyActionResult> | 0 ~ 10 items | List of verify action execution results | |||
| consumeResults | List<EzConsumeActionResult> | [] | 0 ~ 10 items | List of Consume Action execution results | ||
| acquireResults | List<EzAcquireActionResult> | [] | 0 ~ 100 items | List of Acquire Action execution results |
Methods
batchRead
Open multiple messages and claim all rewards at once
Opens up to 10 messages at once and grants all their attached rewards in a single operation. If any of the specified messages has already been opened, an error is returned and none of the messages are processed — this ensures rewards are never claimed twice. Use this for an “Open All” or “Claim All” button on the gift box screen — the player taps one button and receives all pending rewards at once.
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 (.). | ||
| messageNames | List<string> | ✓ | 1 ~ 10 items | List of message names | ||
| gameSession | GameSession | ✓ | GameSession |
Result
| Type | Description | |
|---|---|---|
| items | List<EzMessage> | List of Message |
| transactionId | string | Issued transaction ID |
| stampSheet | string | Stamp sheet |
| stampSheetEncryptionKeyId | string | Cryptographic key GRN used for stamp sheet signature calculations |
| autoRunStampSheet | bool | Whether automatic transaction execution is enabled |
| atomicCommit | bool | Whether to commit the transaction atomically |
| transaction | string | Issued transaction |
| transactionResult | EzTransactionResult | Transaction execution result |
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 |
|---|---|---|
| MessageExpiredException | NotFoundException | Message has expired |
Implementation Example
try {
var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
var result = await domain.BatchReadAsync(
messageNames: new List<string> {
"message-0001",
"message-0002",
}
);
} catch(Gs2.Gs2Inbox.Exception.MessageExpiredException e) {
// Message has expired
}
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
var future = domain.BatchReadFuture(
messageNames: new List<string> {
"message-0001",
"message-0002",
}
);
yield return future;
if (future.Error != null)
{
if (future.Error is Gs2.Gs2Inbox.Exception.MessageExpiredException)
{
// Message has expired
}
onError.Invoke(future.Error, null);
yield break;
}
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). const auto Domain = Gs2->Inbox->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
);
const auto Future = Domain->BatchRead(
[]
{
auto v = TOptional<TArray<FString>>();
v->Add("message-0001");
v->Add("message-0002");
return v;
}() // messageNames
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
auto e = Future->GetTask().Error();
if (e->IsChildOf(Gs2::Inbox::Error::FMessageExpiredError::Class))
{
// Message has expired
}
return false;
}delete
Delete a message from the gift box
Permanently removes a message from the player’s gift box, regardless of whether it has been opened or not. If your gift box is configured to automatically delete messages when they are opened, you don’t need to call this manually. But if auto-delete is disabled (so that opened messages remain visible in the gift box), use this API to let players clean up their inbox. Use this for a “Delete” or “Dismiss” button on individual messages — for example, letting players remove old opened messages they no longer need.
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 | |||
| messageName | string | ✓ | UUID | ~ 36 chars | Message Name Maintains a unique name for each message. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each message. |
Result
| Type | Description | |
|---|---|---|
| item | EzMessage | Message deleted |
Implementation Example
var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Message(
messageName: "message-0001"
);
var result = await domain.DeleteAsync(
); var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Message(
messageName: "message-0001"
);
var future = domain.DeleteFuture(
);
yield return future;
if (future.Error != null)
{
onError.Invoke(future.Error, null);
yield break;
} const auto Domain = Gs2->Inbox->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Message(
"message-0001" // messageName
);
const auto Future = Domain->Delete(
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}
const auto Result = Future->GetTask().Result();get
Get the details of a specific message
Retrieves the full details of a specific message in the player’s gift box, including its metadata (title, body, etc.), read status, attached rewards, and expiration time. Use this to show a message detail screen — for example, “Maintenance Compensation — Sorry for the inconvenience! Here are 100 Gems as compensation. [Open]”.
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 (.). | ||
| messageName | string | ✓ | UUID | ~ 36 chars | Message Name Maintains a unique name for each message. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each message. | |
| gameSession | GameSession | ✓ | GameSession |
Result
| Type | Description | |
|---|---|---|
| item | EzMessage | Message |
Implementation Example
var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Message(
messageName: "message-0001"
);
var item = await domain.ModelAsync(); var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Message(
messageName: "message-0001"
);
var future = domain.ModelFuture();
yield return future;
var item = future.Result; const auto Domain = Gs2->Inbox->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Message(
"message-0001" // messageName
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}Value change event handling
var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Message(
messageName: "message-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.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Message(
messageName: "message-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->Inbox->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Message(
"message-0001" // messageName
);
// Start event handling
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::Inbox::Model::FMessage> 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.
list
Get a list of messages in the player’s gift box
Retrieves all messages in the player’s gift box (present box / inbox), ordered from newest to oldest. Each message can contain rewards (items, currency, etc.) that the player can claim by opening it. You can filter by read status — for example, showing only unopened messages or only opened ones. Use this to build a “Gift Box” or “Presents” screen — for example, showing a list like “Maintenance Compensation (Gems x100)”, “Daily Login Bonus (Gold x500)”, with an “Open” button for each.
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 | |||
| isRead | bool | Read status | ||||
| pageToken | string | ~ 1024 chars | Token specifying the position from which to start acquiring data | |||
| limit | int | 30 | 1 ~ 1000 | Number of data items to retrieve |
Result
| Type | Description | |
|---|---|---|
| items | List<EzMessage> | List of Message |
| nextPageToken | string | Page token to retrieve the rest of the listing |
Implementation Example
var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
var items = await domain.MessagesAsync(
).ToListAsync(); var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
var it = domain.Messages(
);
List<EzMessage> items = new List<EzMessage>();
while (it.HasNext())
{
yield return it.Next();
if (it.Error != null)
{
onError.Invoke(it.Error, null);
break;
}
if (it.Current != null)
{
items.Add(it.Current);
}
else
{
break;
}
} const auto Domain = Gs2->Inbox->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
);
const auto It = Domain->Messages(
);
TArray<Gs2::UE5::Inbox::Model::FEzMessagePtr> Result;
for (auto Item : *It)
{
if (Item.IsError())
{
return false;
}
Result.Add(Item.Current());
}Value change event handling
var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
// Start event handling
var callbackId = domain.SubscribeMessages(
() => {
// Called when an element of the list changes.
}
);
// Stop event handling
domain.UnsubscribeMessages(callbackId); var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
// Start event handling
var callbackId = domain.SubscribeMessages(
() => {
// Called when an element of the list changes.
}
);
// Stop event handling
domain.UnsubscribeMessages(callbackId); const auto Domain = Gs2->Inbox->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
);
// Start event handling
const auto CallbackId = Domain->SubscribeMessages(
[]() {
// Called when an element of the list changes.
}
);
// Stop event handling
Domain->UnsubscribeMessages(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.
read
Open a message and claim its rewards
Opens the specified message and grants any attached rewards (items, currency, etc.) to the player. The message is marked as read and the rewards are delivered in a single operation. If the message has already been opened, an error is returned to prevent claiming rewards twice. If the message has no rewards attached, it is simply marked as read. Use this for the “Open” or “Claim” button on each message in the gift box — for example, the player taps “Open” and receives “Gems x100”.
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 (.). | ||
| messageName | string | ✓ | UUID | ~ 36 chars | Message Name Maintains a unique name for each message. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each message. | |
| gameSession | GameSession | ✓ | GameSession |
Result
| Type | Description | |
|---|---|---|
| item | EzMessage | Message |
| transactionId | string | Issued transaction ID |
| stampSheet | string | Stamp sheet |
| stampSheetEncryptionKeyId | string | Cryptographic key GRN used for stamp sheet signature calculations |
| autoRunStampSheet | bool | Whether automatic transaction execution is enabled |
| atomicCommit | bool | Whether to commit the transaction atomically |
| transaction | string | Issued transaction |
| transactionResult | EzTransactionResult | Transaction execution result |
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 |
|---|---|---|
| MessageExpiredException | NotFoundException | Message has expired |
Implementation Example
try {
var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Message(
messageName: "message-0001"
);
var result = await domain.ReadAsync(
);
} catch(Gs2.Gs2Inbox.Exception.MessageExpiredException e) {
// Message has expired
}
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Message(
messageName: "message-0001"
);
var future = domain.ReadFuture(
);
yield return future;
if (future.Error != null)
{
if (future.Error is Gs2.Gs2Inbox.Exception.MessageExpiredException)
{
// Message has expired
}
onError.Invoke(future.Error, null);
yield break;
}
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). const auto Domain = Gs2->Inbox->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Message(
"message-0001" // messageName
);
const auto Future = Domain->Read(
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
auto e = Future->GetTask().Error();
if (e->IsChildOf(Gs2::Inbox::Error::FMessageExpiredError::Class))
{
// Message has expired
}
return false;
}receiveGlobalMessage
Receive messages sent to all players
Checks for global messages (messages sent to all players at once, such as maintenance compensation or event rewards) and delivers any that this player hasn’t received yet to their gift box. Each global message is converted into an individual message in the player’s inbox. Messages already received are skipped, so calling this multiple times is safe. Call this when the player opens the gift box screen or logs in, to make sure they have all global messages available. Use this as part of the gift box initialization — call it before listing messages to ensure the player sees all global gifts.
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 |
Result
| Type | Description | |
|---|---|---|
| item | List<EzMessage> | List of received messages |
Implementation Example
var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
var result = await domain.ReceiveGlobalMessageAsync(
);
var item = await result.ModelAsync(); var domain = gs2.Inbox.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
var future = domain.ReceiveGlobalMessageFuture(
);
yield return future;
if (future.Error != null)
{
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->Inbox->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
);
const auto Future = Domain->ReceiveGlobalMessage(
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
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();Event Handler
OnReceiveNotification
Push notification used when a message is received
| Name | Type | Description |
|---|---|---|
| namespaceName | string | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
| userId | string | User ID |
| messageName | string | Message Name Maintains a unique name for each message. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each message. |
Implementation Example
gs2.Inbox.OnReceiveNotification += notification =>
{
var namespaceName = notification.NamespaceName;
var userId = notification.UserId;
var messageName = notification.MessageName;
}; gs2.Inbox.OnReceiveNotification += notification =>
{
var namespaceName = notification.NamespaceName;
var userId = notification.UserId;
var messageName = notification.MessageName;
}; Gs2->Inbox->OnReceiveNotification().AddLambda([](const auto Notification)
{
const auto NamespaceName = Notification->NamespaceNameValue;
const auto UserId = Notification->UserIdValue;
const auto MessageName = Notification->MessageNameValue;
});