Unity SDK v0.1.0 C#
The official Keme SDK for Unity brings drop-in, in-app player support directly into your game — authentication, tickets, and knowledge base, backed by the Keme portal REST API, plus a runtime support panel your players can open without you building any UI.
Overview
The SDK lives in the Keme namespace, ships as the UPM package com.keme.sdk, and uses async/await over UnityWebRequest. It has zero dependencies beyond Unity's built-in uGUI (com.unity.ugui).
- Unity 2021.3+ (works on all platforms including WebGL, iOS, and Android)Zero external dependencies — no NuGet or third-party JSON libraryInstall via Unity Package Manager (UPM git URL) or manual copyDrop-in runtime support panel — no prefab or scene wiring requiredContinuations resume on Unity’s main thread, so it’s safe to touch the UI right after an await
github.com/kemegames-studio/keme-sdk under the /unity path. Every Keme SDK wraps the same portal REST contract.Installation
Option A — UPM git URL (recommended)
In Unity, open Window → Package Manager → + → Add package from git URL… and paste:
1https://github.com/kemegames-studio/keme-sdk.git?path=/unity
Or add it directly to your Packages/manifest.json:
1{2 "dependencies": {3 "com.keme.sdk": "https://github.com/kemegames-studio/keme-sdk.git?path=/unity"4 }5}
Unity resolves and downloads the package automatically when you open the project or click Refresh in the Package Manager window.
Option B — Manual
Copy the unity folder into your project's Packages/ directory (as Packages/com.keme.sdk), or drop the Runtime/ folder anywhere under Assets/.
DemoBootstrap component to an empty GameObject, fill in your gameId / userId, and press Play.Quickstart
Three lines get you a fully working support surface. Init creates the client, Login authenticates the player (auto-provisioning them on first contact), and OpenSupport shows the drop-in panel.
1using Keme;23var keme = KemeSDK.Init(new KemeConfig4{5 GameId = "your-game-id",6 AppName = "Your Game Support",7});89await keme.Login(player.Id, player.Name); // auto-provisions the player, persists token10keme.OpenSupport(); // runtime drop-in support panel
KemeSDK.Init also stashes the client on KemeSDK.Default, so a UI button handler can call KemeSupport.Open(KemeSDK.Default) without threading a reference through your scene.
Task, so call them from an async method (async void Start() in a MonoBehaviour is fine). Continuations resume on Unity's main thread.Configuration
Create the client with KemeSDK.Init(KemeConfig), which returns a KemeClient.
| Field | Type | Notes |
|---|---|---|
| GameId | string | Required. The game/app tickets are filed against. |
| ApiBase | string | Optional. Defaults to https://api.kemegames.com/api/v1. |
| AppName | string | Optional. Support panel header. Defaults to "Support". |
| Storage | ITokenStorage | Optional. Defaults to PlayerPrefsTokenStorage (key keme.portal.token). |
Authentication
Call Login with the player's userId (and optional display name / email). The first login for a given userId auto-provisions the player — there is no separate registration step — and the returned 7-day token is persisted automatically.
1// Either overload works2await keme.Login(new LoginParams("player-123", "Ari"));3await keme.Login("player-123", "Ari", "ari@example.com");45bool signedIn = keme.IsLoggedIn(); // true when a token is stored6Player me = await keme.GetPlayer();78keme.Logout(); // clears the persisted token
KemeException with Status == 403. Reuse the same userId for the same player across sessions and devices so their ticket history follows them.The Support Panel
keme.OpenSupport() (or KemeSupport.Open(client)) builds a full uGUI panel at runtime — Canvas, ticket list, ticket detail with reply, and a "new ticket" form with category picker — no prefab or scene wiring needed. It auto-creates an EventSystem if your scene lacks one.
1// Open the drop-in support panel (player must be logged in first)2keme.OpenSupport();34// Or from a static context, using the default client5KemeSupport.Open(KemeSDK.Default);67// Close it programmatically8KemeSupport.Close();
#4F46E5. Close it with the ✕, the backdrop, or KemeSupport.Close(). The player must be logged in first, since the panel calls authenticated endpoints.Tickets
Access ticket operations through client.Tickets. Subjects are 5–200 characters and descriptions are 10–5000. The ticket is filed against the config GameId unless you override it.
1using Keme;23// Create a ticket4Ticket ticket = await keme.Tickets.Create(new CreateTicketParams5{6 Subject = "Lost my gems after the update",7 Description = "I had 500 gems before v1.4 and now they're gone.",8 Category = TicketCategory.Billing,9 Priority = TicketPriority.P2,10});1112// List the player's tickets (paginated, normalised to a plain list)13Listmine = await keme.Tickets.List(new ListTicketsParams { Page = 1, Limit = 20 }); 1415// Fetch a single ticket, including its message thread16Ticket detail = await keme.Tickets.Get(ticket.Id);1718// Reply to a ticket (body 1–5000)19TicketMessage reply = await keme.Tickets.Reply(ticket.Id, "Any update?");2021// Rate a resolved ticket (score 1–5)22await keme.Tickets.Rate(ticket.Id, 5, "Fast fix, thanks!");
Categories & priorities
- TicketCategory: Bug | Billing | Account | Gameplay | Other (serialized lower-case)TicketPriority: P1 | P2 | P3 | P4
Knowledge Base
Access self-serve help content through client.Kb so players can find answers before opening a ticket.
1Listresults = await keme.Kb.Search("gems"); 2Listcategories = await keme.Kb.Categories(); 3Listfeatured = await keme.Kb.Featured(); 4KbArticle article = await keme.Kb.Article("how-to-restore-purchases");
Models & Errors
The core models are Player, Ticket, TicketMessage, KbArticle, and Game. Every model exposes both JSON-shaped camelCase fields (e.g. player.gameUid) and idiomatic PascalCase properties (e.g. player.GameUid) — use whichever you prefer.
Any non-2xx response throws KemeException { Message, Status, Body }. Network/transport failures throw with Status == 0. The server's message (string or string[]) is flattened into Message.
1try2{3 await keme.Tickets.Create(new CreateTicketParams { Subject = "Hi", Description = "Too short" });4}5catch (KemeException e)6{7 Debug.LogError($"({e.Status}) {e.Message}"); // e.Body has the raw JSON8}
gameId vs userId
These are two different identifiers — do not mix them up:
- gameId identifies the game/app (e.g. game-marble-sort). Set it once in KemeSDK.Init; it is attached to every ticket. Fetch valid ids with keme.Games().userId identifies the player within your game, and maps to the portal gameUid. Pass it to Login. The first login auto-provisions the player — no separate registration step.
PlayerPrefs (works everywhere, including WebGL). Implement ITokenStorage and pass it in KemeConfig.Storage to use your own (e.g. encrypted) store.