Unity SDK

Promo Codes

Two complementary helpers: PromoCodeRedeemer for the in-game client, and PromoCodeIssuer for partner / influencer integrations that need to mint codes from a trusted backend.

Overview

Codes are authored on the dashboard with their reward (currency, items, bundles) and consumability rules. The server enforces single- and shared-redemption limits - the SDK is purely a thin transport.

Redeeming a code

exampleC#
1using KalmForge;
2
3var result = await PromoCodeRedeemer.RedeemCode("WELCOME2026");
4if (result.success) {
5 Debug.Log($"Got {result.reward_data.amount} {result.reward_data.type}");
6} else {
7 Debug.LogWarning($"{result.ErrorCodeEnum}: {result.error}");
8}

Error codes

Strongly typed via RedeemResponse.ErrorCodeEnum:

NameTypeDescription
INVALID_REQUESTErrorCodeEmpty code or missing fields.
INVALID_FORMATErrorCodeServer response could not be parsed.
MISSING_PROJECT_IDErrorCodeX-Project-Id header missing.
CODE_NOT_FOUNDErrorCodeCode does not exist.
CODE_NOT_ISSUEDErrorCodeCode is in a campaign but has not been issued yet.
CODE_ALREADY_REDEEMEDErrorCodeThis player already redeemed this code.
CODE_LIMIT_REACHEDErrorCodeShared code is out of remaining redemptions.
INTERNAL_ERRORErrorCodeServer-side failure. Safe to retry.
NETWORK_ERRORErrorCodeConnection failure. Safe to retry.

Shared (non-consumable) codes

exampleC#
1if (!result.is_consumable && PromoCodeRedeemer.HasRemainingUses(result)) {
2 Debug.Log($"{result.remaining_redemptions} of {result.max_redemptions} left");
3}
Note
max_redemptions = -1 means unlimited. HasRemainingUses returns true in that case.

Issuing codes (partner integrations)

PromoCodeIssuer is intended for trusted server-side use (a creator portal, an affiliate webhook). Hard-code the partner API key on the server, never in the Unity client.

exampleC#
1var issuer = new PromoCodeIssuer(partnerApiKey);
2var resp = await issuer.IssueCode(campaignId: "creator_alpha", partnerPromoCode: "LIVESTREAM");
3if (resp.success) Debug.Log($"Issued {resp.reward_code} (request {resp.request_id})");

API reference

PromoCodeRedeemer - static API
NameTypeDescription
RedeemCode(code)Task<RedeemResponse>Redeem a single code for the current player.
HasRemainingUses(response)bool (static)Helper for shared (non-consumable) codes.
RedeemResponse - fields
NameTypeDescription
successboolTrue on a successful redemption.
campaign_idstringSource campaign of this code.
reward_typestring"coins" | "gems" | "item" | "bundle" | …
reward_dataRewardDatatype / amount / item_id.
is_consumableboolTrue for one-shot personal codes.
redemption_count / max_redemptions / remaining_redemptionsint-1 = unlimited / not provided.
error_codestringStable enum (see ErrorCodeEnum).
errorstringHuman-readable detail.
PromoCodeIssuer - instance API
NameTypeDescription
new PromoCodeIssuer(partnerApiKey)ctorServer-side only. Reads ProjectId + endpoint from KalmForgeClient.
IssueCode(campaignId, partnerPromoCode?)Task<IssueResponse>Mint and return a single reward_code.

REST endpoints

examplebash
1# Redeem (client)
2POST /api/public/promo/redeem
3Headers: X-Project-Id: PROJECT
4{ "reward_code": "WELCOME2026", "player_id": "...", "device_id": "..." }
5
6# Issue (partner backend)
7POST /api/public/promo/issue
8Headers:
9 Authorization: Bearer kf_partner_xxx
10 X-Project-Id: PROJECT
11 X-Request-ID: <uuid> # idempotency key
12{ "campaign_id": "creator_alpha", "partner_promo_code": "LIVESTREAM" }
Back to DocsKalmForge SDK · v1.0.1