Skip to content
Stove
Last Updated

Curious about the actual application flow?

Usage Scenarios / Purchasing in the Game

Coupon

Understanding


By integrating the STOVE platform's coupon service, you can issue coupons in STOVE Partners and grant rewards such as items to users in the game or on the web.
Coupons are used to boost user retention through pre-registration/collab/event rewards, marketing-inflow/conversion tracking, manual CS rewards, and more.

Coupon pop-up coverage and display location
ㅁ SDK pop-up support: mobile games, multi-platform (PC+mobile) games (including PC builds)
ㅁ iOS/PC-only games: register via the STOVE website coupon box or the game homepage instead of the SDK pop-up
ㅁ Display location: designated by the CP company (developer) to fit the game UX (e.g., main lobby > settings > register coupon)

Coupon Types and Rewards

Looking at coupon types and reward composition together helps you pick the right coupon for your situation.

Which coupon should you use?

First pick the coupon type that fits your situation.


Coupon-type selection guide

Does the user enter the code themselves?

├─ Yes · one unique code per person (pre-registration/CS/personal events) → Standard coupon

├─ Yes · one shared code used by many (SNS/collab) → Representative (shared) coupon

├─ Yes · only pre-registered targets can enter/use the code (beta/tier-only) → Targeted coupon

├─ No · granted directly to specific user accounts (VIP/CS/attendance) → Account-grant coupon

└─ No · granted directly to the accounts of users who downloaded it (currently used mainly in the store) → Download coupon

Coupon types

The issuance method and the user's experience of receiving a coupon differ by coupon type.

Coupon type Category Characteristics Main use
Standard coupon 1 : 1 One code used by one person; the user enters the code Pre-registration/personal events/CS rewards
Representative (shared) coupon 1 : N One code used by many; a public code is entered Collab/SNS/seasonal events
Account-grant coupon Automatic grant Loaded into the coupon box automatically, no entry VIP/error/manual CS rewards
Targeted coupon Designated targets only Usable only by registered targets (target verification) Beta testers/tier-only events
Download coupon Store integration Downloaded from the store, then loaded into the coupon box (extra integration needed)
※ If the CP company builds and integrates its own download coupon box, it can be used in-game too, but it's currently used mainly in the "store"
Driving store visits
What to give as a reward? (Coupon attributes)

If a coupon's type is "to whom · how to distribute," a coupon's attribute is "what to give."
When issuing, the order is to decide the type first, then set the attribute (reward).


Reward type What is given Characteristics / constraints
Item coupon In-game items/currency Granted by member number or character number
Discount coupon A discount at payment (fixed amount / percentage) Usable both in-game and in the store
※ In-game discount coupons are used at the payment window
※ Cart/bundle discount options are store-only
Game-pass coupon A pass to play a store game for free Usable only in the store
Common combination examples (type × reward)

"In this case, do this" — combinations that are actually used often.

This combination for this case

· Handing out items via SNS/collab → Representative (shared) coupon + item

· Per-person item grants / pre-registration / CS rewards → Standard coupon + item

· Granting items directly to a specific user (VIP/error rewards) → Account-grant coupon + item

· In-game payment-discount events → Standard or representative (shared) coupon + discount (users apply it at the payment window)

· Granting game passes to creators/promoters (offering trials) → Account-grant coupon + game pass

Screen Examples by Setting

The screen and experience users see in-game differ by coupon type and detailed settings.

Setting combination User screen
Standard coupon + fixed prefix (Prefix) First 4 characters fixed (e.g., FREEXXXXXX) → gives a branded-coupon feel, suitable for events/collabs
Representative coupon + auto-generated random code Enter a public code (e.g., 2350DWG06Z0009S5) in-game; first-come and time-limit settings are possible
Account-grant coupon (no entry) Loaded into the coupon box automatically without entry; checked via notification/coupon box

Coupon Issuance Flow

This is the full flow from issuing a coupon to delivering it to users.

Step 1. Set coupon info

In Partners [Billing > Coupon Management > Coupon Info Settings], enter the coupon type, reward, representative image, etc.

ℹ️ This step only needs to be set once. Once set, you don't need to redo it each time you issue, and you only edit it when you want to change settings like type or reward. Actual coupon issuance repeats from Step 2.

Coupon-info-settings notice
ㅁ Set the coupon type/attribute to use (required before issuance)
ㅁ STOVE coupon box use = Y → the game name is shown in the My Info coupon box (ascending by group)
ㅁ The game-pass attribute is store-only
ㅁ For the representative image, the Info Settings menu value takes priority over the issuance image
ㅁ When the game name is set to STOVE, coupon maintenance can be configured


Step 2. Issue the coupon

In Partners [Billing > Coupon Management > Issue Coupon], set basic info like the coupon name and the type/attribute.

Coupon info (name, description, reward text, cautions)
ㅁ Multilingual support; enter the in-game display text (item-reward text)
ㅁ Copy coupon info: entering an existing coupon ID auto-loads most of the issuance info


Coupon type and attribute
ㅁ The default usage country is all (configure separately if you want only some countries)
ㅁ Type/attribute are loaded from the Info Settings menu (download coupons are store-only; attributes are used when reward info is linked)
ㅁ Depending on the type, choose a directly specified custom code (designated word) or a fixed prefix (Prefix)


Issuing item coupons
ㅁ Add item selections to issue up to 50 (bulk issuance such as attendance rewards)
ㅁ Granted by member number by default; issuance by character number is possible (representative coupon + item attribute only)


Issuing discount coupons
ㅁ Fixed-amount / percentage settings (fixed amount = some items only, percentage = all items only)
ㅁ Fixed amounts are auto-calculated in USD (using the previous month's last-day exchange rate)
ㅁ Cart/bundle discounts are store-only



Sharing discount costs
ㅁ Discount costs and partner fees can be set to be shared between the platform and the CP company
ㅁ It affects settlement, so consultation with the contact is required


Step 3. Deliver to users

Deliver the code via events/SNS/CS, etc.; account-grant and download coupons are loaded automatically.

Receiving event-participation rewards



Step 4. User receipt

Registering it in the in-game coupon-input window or auto-checking it in the coupon box grants the reward (item/discount).

In-game coupon-registration example



In-game discount-coupon usage example
ㅁ Unlike store discount coupons, in-game discount coupons are used at the payment window.


Display location by platform/channel

Platform/channel Display location Notes
Mobile (Android) In-game [Register Coupon] button → SDK coupon pop-up Recommended for Android
Mobile (iOS) In-app display not recommended In-app input UI / external web links can be grounds for rejection (Apple guidelines)
PC (Windows) In-game [Register Coupon] button → SDK pop-up or STOVE/game official homepage SDK pop-up for multi-platform games only
STOVE official website My Info > Coupon Box Unified coupon entry, login required
Game official homepage Integrate the STOVE coupon API in your own UI Requires API calls; design customization is possible

Development


Mobile (SDK) - Using Coupons

Using a coupon is done with a single call to the SDK-provided View.useCoupon. The SDK requests use-processing from the STOVE ItemBox server and handles the flow through to the game-server callback (item grant). Coupon-box list search, detail lookup, and coupon-box coupon use are in the server REST API domain, not the SDK, so see the Server Integration - ItemBox section.

Caution for iOS
Under Apple guidelines, showing an in-app coupon-input UI can be grounds for rejection.
Don't show an in-game coupon-input screen in iOS builds.

Prerequisites

  • The user must be logged in.
  • Pop-up info must be registered in Partners for it to work (except for the direct-call page method).

Notice
Partners configuration is done through the publishing technical contact.

Development Flow

  1. Collect the coupon number : Receive the coupon number the user entered in the in-game coupon-input screen.
  2. Call coupon use : Calling View.useCoupon(context, code, callback) has the SDK process the use with the ItemBox server.
  3. Handle the result : Branch success/failure with the Result passed in the callback. : On failure, delegating to OperationUI.HandleResult(result, ...) shows the SDK's common guidance screen.

Troubleshooting

  • ErrorCodes
    DomainErrorCodeDescriptionAction
    com.stove.server100A coupon usable only in a PC cafeShow a usage-environment notice and keep the input screen open.
    com.stove.server997Not Verify AccessTokenRe-fetch Auth.accessToken and call again. If the same error persists, guide the user into the login flow to get a reissued token.
    com.stove.server998Expired AccessTokenGuide the user into the login flow to get a reissued token.
    com.stove.server999System Error
    com.stove.server2605This membership account cannot use it.
    com.stove.server5031You've exceeded the daily verification count.Show a notice and guide the user to retry after a while.
    com.stove.server5105Invalid coupon number.Show a re-check-the-coupon-number message and reset the input screen.
    com.stove.server5125This coupon has already been used.Reset the input screen and show an already-used notice.
    com.stove.server5130This coupon has been disabled.
    com.stove.server5135This coupon has expired.Reset the input screen and show an expiry notice.
    com.stove.server5155You've exceeded this coupon's usage limit.Reset the input screen and show a notice.
    com.stove.server5161This coupon's registration period has expired.
    com.stove.server5162This coupon can't be used in your country.
    com.stove.server5164This coupon can't be used in this world.
    com.stove.server5165This coupon can only be used from the coupon box.
    com.stove.server5169It's not within this coupon's usage period.
    com.stove.server5200You're not an eligible target for this coupon.
    com.stove.server5202This coupon is already registered in the coupon box.
    com.stove.server6002This coupon number can no longer be used.
    com.stove.server6026The usage count has been exceeded.Reset the input screen and show a notice.

Cases with clear user guidance
Show in-game notices for cases like invalid coupon number (5105), already-used coupon (5125), expired coupon (5135), and usage-count exceeded (5155 / 6026).
Retrying an already-expired/used coupon is meaningless, so reset the input screen.

Sample Code

csharp
public void UseCoupon()
{
    /**
     * code : coupon input (string)
     **/
    View.UseCoupon("code", (Result result) =>
    {
        if (result.IsSuccessful)
        {
        }
        else
        {
            OperationUI.HandleResult(result, (Result operationResult) =>
            {
                /** ex) keep the current screen **/
            });
        }
    });
}

On Android, the SDK-provided input UI is also available
Calling ViewUI.coupon shows the STOVE standard coupon-input screen as-is, and when the user enters a code, the SDK proceeds through use-processing and item grant.
(Android only, not supported on iOS) For detailed usage and sample code, see In-game features — Using coupons (Android only).

PC (PCSDK) - Coupon Pop-up

Using the coupon pop-up API provided by PCSDK ViewSDK, you can show the STOVE coupon-input screen inside the game client. When the user enters the coupon number directly in the pop-up, STOVE proceeds with the use-processing and item-grant flow.

The PC SDK coupon pop-up is available only for multi-platform (PC + mobile) games.
The call works correctly only for games registered as mobile games and designated for multi-platform use in Partners > Launching > Service Integration.
For single-platform (PC-only) games, replace this with a flow where the game builds its own coupon-input UI and calls the coupon-registration API directly.

Prerequisites

  • After BaseSDK initialization (Base_Initialize or Base_InitializeEx) completes, initializing ViewSDK (View_Initialize) lets you use the coupon pop-up API.
  • Base_RunCallback() must be called periodically in the game loop for async callbacks to work.
  • If using a built-in WebView (WebViewMode::INTERNAL) pop-up, initialize with View_InitializeWithWndInfo(mainWndHandle), passing the game's main HWND, instead of View_Initialize.

Development Flow

  1. Initialization : After completing BaseSDK initialization with Base_Initialize (or Base_InitializeEx), call View_Initialize(). If using a built-in WebView pop-up, initialize with View_InitializeWithWndInfo(mainWndHandle), passing the game's main HWND, instead of View_Initialize.
  2. Call the coupon pop-up : When the user requests the coupon-input UI, call View_CouponPopup or View_CouponPopupEx.
    • C/C++ : call View_CouponPopup(mode, onFinished). To also receive the pop-up-close event, use View_CouponPopupEx(mode, onFinished, onDestroy). mode is a WebViewMode value.
    • C# : call View_CouponPopup(mode, onFinished) or View_CouponPopupEx(mode, onFinished, onDestroy).
    • onFinished is called when the pop-up finishes displaying, and onDestroy when the pop-up's native resources are fully cleaned up.
  3. Choose WebViewMode : Set mode to WebViewMode::EXTERNAL (external browser) or WebViewMode::INTERNAL (SDK built-in WebView), whichever fits your game environment. : Exclusive-fullscreen games must use WebViewMode::EXTERNAL.
  4. Handle close : Receive the onDestroy callback to resume the game flow. If you need to refresh the inventory after coupon use, do it after this callback.
  5. Cleanup : When done with the coupon pop-up, clean up ViewSDK with View_UnInitialize(), and call Base_UnInitialize() just before the game exits.

Troubleshooting

SituationCauseSolution
I called the coupon pop-up but nothing happensThe coupon pop-up is a feature for multi-platform (PC + mobile) games only. Calling it from a game registered as single-platform in Partners won't work.Check that the game is registered as multi-platform in Partners. For single-platform games, replacing it with a flow that shows the game's own coupon-input screen avoids issues.
The coupon pop-up is hidden behind the game windowIf you initialize with View_Initialize without a parent window handle, the pop-up appears as a separate window and can go behind the game window. In exclusive-fullscreen mode, built-in WebView (WebViewMode::INTERNAL) pop-ups can't come above the game window due to Windows API limits.Initialize by passing the game's main HWND to View_InitializeWithWndInfo(mainWndHandle). For exclusive-fullscreen games, always calling the pop-up in external-browser (WebViewMode::EXTERNAL) mode avoids issues.
The pop-up result callback isn't calledIf you don't call Base_RunCallback() in the main loop, the SDK can't find a point to deliver results to the game.Call Base_RunCallback() every frame or at a regular interval in the main loop.

Sample Code

cpp
#include "ViewSDK.h"

using namespace Stove::PCSDK;
using namespace Stove::PCSDK::Base;
using namespace Stove::PCSDK::View;

// 1) Initialize ViewSDK (after Base_Initialize completes)
auto initResult = View_Initialize();
if (!initResult.IsSuccessful())
{
    return;
}

// 2) Coupon pop-up (Ex version: receive the close event)
View_CouponPopupEx(
    WebViewMode::EXTERNAL,
    [](CallbackResult openResult)
    {
        if (openResult.GetResult().IsSuccessful())
        {
            // Handle pop-up open
        }
    },
    [](CallbackResult destroyResult)
    {
        // Resume the game flow when the pop-up closes
    }
);

// 3) Clean up on exit
View_UnInitialize();

Server Integration - ItemBox

When a user participates in an event, the game server must be integrated to receive and process reward-grant requests. Reward-grant requests are delivered as real-time callback notifications from STOVE's ItemBox server, and the game server should receive the request and process the appropriate reward grant.

Prerequisites

The items below must be registered in advance through Partners

  1. Select the ItemBox integration type: Select "Call from the STOVE server to the game server (including Transaction Id)". Location: Partners > Launching > Service Integration > SDK Runtime Environment Settings

  1. Register a default world: Even games that don't need worlds must designate a default world. (e.g., world_kr). Location: Partners > Launching > SDK Runtime Environment (MO) > World/Channel Info tab

  1. Register the callback server URL: Register the callback server URL that will receive item-grant requests. Location: Partners > GM > Service Integration > ItemBox Integration Environment (mo)

How to set up a loopback URL
The callback server (URL) must be prepared by the CP company, but if it's not ready yet and you need to test in Partners, you can use the loopback URL setup below.
Sandbox: http://i-api.gate8.com/itembox/v2/item/inboundReward
ACL work is needed to communicate with ItemBox. The STOVE platform doesn't need a separate service-opening policy; only the game server must perform the inbound-opening work.

Item-Grant API

This describes the API integration spec that the CP company must provide.


API integration info

text
POST {URL info registered in Partners}
Content-Type: application/json

Request

  • Body
NameTypeRequiredExampleDescription
msg_idStringYbaf84a85-abcc-49fc-ba85-54b7c38331e9The msg ID is generated each time ItemBox sends to the game server
(unique per send)
msgStringY"aWLoj83ZxAICnRfjA+ayhd7nn1V/Fh/3I....3Of7N0s45uDN6DJjAjwqc="Delivered encrypted; decryption required
timestampLongY1480512039The Msg's timestamp (seconds from Jan 1, 1970 to the current time)
  • msg payload before encryption
NameTypeRequiredExampleDescription
game_idStringYSTOVE_GAMEGame ID
world_idStringYworld_globalWorld ID
member_noLongY503510The platform user's guid (member_no for legacy games)
nickname_noLongY1603829809The platform user's nickname_no
item_idStringYITEM_K001Game item ID
transaction_idStringY6b384ab9d65f422db0abf186a7f79311transaction id (the transaction key value; the game server uses it to determine duplicate grants)
service_typeStringYCOUPONService type
"COUPON" : sent via coupon use
"EVENT" : sent via an event
item_amtIntegerY3Item quantity
reward_msgStringNThis is a reward for pre-registration event participationThe message to show the user when granting the item
(the content registered when creating the coupon)
end_dtStringN20150116The item-grant expiry date (DateFormat: "yyyyMMdd", Default: 1 month from the request time)
payloadObjectN{
"item_period" : 0
}
ItemBox passes data the CP company needs in this json object
(for example: for time-limited items, if there are permanent, 7-day, 30-day, and 60-day options



Response

The game server must respond (in application/json format) to the ItemBox Call API's processing result using the return codes specified below. Content-Type : application/json


  • Body
NameTypeRequiredExampleDescription
return_codeIntegerY0Processing result code
return_messageStringYOKProcessing result message - deliver an identifiable message within 50 characters

  • Return Code
Return codeHTTP Status CodeDescriptionItemBox behavior and reprocessing
0200 okGrant success (also the same for an already-granted transaction_id)Grant success
40001200 okServer internal error (used for cases where re-calling the API can still grant the item)Grant failed - reprocessing proceeds
40002200 okThe requested item doesn't existGrant failed - no reprocessing
40003200 okUser info mismatchGrant failed - no reprocessing
40004200 okMessage decryption failedGrant failed - no reprocessing



Sample

  • Request
    • This is the Request Body in unencrypted form. When actually sent to the game server, the "msg" json value part is encrypted.
    • For decryption, take the received msg data, apply BASE64 Decoding, and then apply AES256 Decryption.
    json
    {
        "msg_id": "baf84a85-abcc-49fc-ba85-54b7c38331e9",
        "msg" :
        {
            "game_id":"STOVE_GAME",
            "world_id":"world_global",
            "member_no": 503510,
            "nickname_no": 1603829809,
            "item_id": "ITEM_K001",
            "transaction_id":"6b384ab9d65f422db0abf186a7f79311",
            "service_type":"COUPON",
            "item_amt":3,
            "reward_msg":"This is a reward for pre-registration event participation",
            "end_dt":"20150116",
            "payload":
            {
                "item_period":0
            }
        },
        "timestamp": 1480512039
    }
    
  • Response
    json
    - Content-Type : application/json
    {
        "return_code": 0,
        "return_message": "Success."
    }
    



Decryption (decrypt) process

  • To ensure stability and validity of requests between the ItemBox system and the game server, some data (Json Data - msg values) is encrypted when sent. Decryption is needed to read the message body.
  • Encryption (encrypt) method: AES256
  • Decryption (decrypt) key: Client Secret Key
  • Transformation: AES/CBC/PKCS5Padding
  • IV Spec: the first 16 characters of the 'Client Secret Key' value
  • Decryption order: take the received msg data, apply BASE64 Decoding, then apply AES256 Decryption.
  • Secret Key location: Partners > Launching > Service Integration > Platform Integration Keys > Mobile Service Integration Key > Client Secret Key



Duplicate-grant protection

  • transaction_id is a unique value auto-generated when a grant request occurs; it's used to prevent missed and
    duplicate item grants between the game server and ItemBox.
  • On successful reward grant, the game server must store the transaction_id in-game and manage it to prevent duplicate grants.
  • If the ItemBox server requests an already-granted transaction_id, the game server can just send response Data "return_code" as "0".



Automatic re-request for failures

  • If sending to the game server fails due to a network failure/server error, the STOVE ItemBox service retries the failed case
    once every 10 minutes, up to 5 times. In this case, the "transaction_id" in the "msg" json is used as the distinguishing key for the failed case, so the game server
    must keep a record of cases successfully granted and processed by "transaction_id".
  • If the game server processed the grant but the ItemBox platform treated it as failed due to a missing reply or a network error,
    a re-grant request can occur.

Troubleshooting

SituationCauseSolution
The item-grant API isn't calledOccurs when not all prerequisite steps are performed correctlyCheck via Partners that the prerequisite settings were done correctly.
Also check that external API calls aren't blocked at the CP company's server infrastructure.
Message decryption failsOccurs when the decryption process isn't performed correctly.Check the guide's decryption-process chapter and integrate using the correct decryption key

Frequently Asked Questions



Q1. What's the difference between the direct-grant method and the coupon-box method?
A. The direct-grant method requests the coupon's reward to be granted to the game immediately when the coupon is used.
The coupon-box method registers the coupon in the user's coupon box, manages it there, and then uses it, adding coupon-list check and detail-lookup steps in between.
Q2. Can't I provide a coupon-registration UI directly on iOS?
A. Under Apple guidelines, external-reward input or purchase-inducing pages are restricted, so it must be handled outside the app.
Don't provide a direct coupon-input feature within the iOS app, and set up explicit alternative guidance to avoid policy rejection.
Q3. Can guest accounts enter coupons too?
A. If the user can be identified via STOVE authentication (GUID-based), coupon entry is possible.
Q4. What happens if I map multiple items to one coupon?
A. If you map multiple items to one coupon, grant requests are sent to the game server for as many items as are mapped.
Create an in-game product such as a bundle for the reward so that you receive only a single grant request.
Q5. How do I protect against duplicate grants?
A. Store the transaction_id in-game and manage it to prevent duplicate grants.
If the ItemBox server re-requests an already-granted transaction_id, the game server can send response Data "return_code" as "0".
Q6. What happens if the ItemBox callback fails?
A. If sending to the game server fails due to a network failure/server error, the STOVE ItemBox service automatically retries once every 10 minutes, up to 5 times.
Since the same transaction_id is used on retry, the game server can respond with a "0" return_code for already-processed cases without a duplicate grant.
Q7. How do I handle a failed item grant due to maintenance or an outage?
A. There's a reprocessing feature in the Partners menu; for failed cases, you can reprocess the grant in the Partners GM > Grant-Failure Reset (mo) menu.



Need to contact us directly? stove.developers@smilegate.com