Player identity

How Inngame knows who is writing, and how a player's history follows them from their phone to their PC.

Anonymous by default

The first time the SDK starts on a device, it opens a session and receives a private device token. That device is an anonymous player: they can chat right away, no login needed. The token is stored locally (PlayerPrefs in Unity by default).

Unverified identity

Pass your own account id. The team sees it with a name and email, and it stays on this device's player.

await Inngame.Identify("player-1842", "Camille", "camille@example.com");

An unverified id is a label, not a proof: anyone can send any id from a modified build. So Inngame never uses it to join devices. Two devices that send the same unverified id stay two separate players, and neither sees the other's messages. If the id belongs to a verified player, the call is refused (identity_requires_token). To make history follow a player across devices, use a JWT or Steam.

Some fields are set by the server only and are ignored in player metadata: subscription_status, paid, is_paying, plan, and the RevenueCat fields. They come from your store webhooks, so a player can't make themselves a subscriber. The same applies to subscription events and event names starting with inngame., which the SDK can't send.

For purchases, each player gets a purchase token (a UUID issued by Inngame, Inngame.PurchaseToken in Unity, Inngame.purchaseToken on iOS). Pass it to the store or to your subscription service; Inngame matches subscription events by that token, or by the account id of a verified player. See Integrations.

Verified identity with a JWT

Your game server signs a short-lived JWT with the app's identity secret (inbox → Settings → Apps → your app). The SDK passes it to Inngame, which checks the signature.

// Node.js, on your game server (npm i jsonwebtoken)
import jwt from "jsonwebtoken";

app.get("/inngame-token", requireLogin, (req, res) => {
  const token = jwt.sign(
    { user_id: req.user.id, name: req.user.displayName, email: req.user.email },
    process.env.INNGAME_IDENTITY_SECRET,
    { algorithm: "HS256", expiresIn: "10m" }
  );
  res.json({ token });
});
# Python, on your game server (pip install pyjwt)
import time, jwt

def inngame_token(user):
    return jwt.encode(
        {"user_id": user.id, "name": user.display_name, "exp": int(time.time()) + 600},
        INNGAME_IDENTITY_SECRET,
        algorithm="HS256",
    )
// In the game
string jwt = await MyBackend.Get("/inngame-token");
bool ok = await Inngame.IdentifyWithToken(jwt);

A bad signature, a missing user_id or an expired token is rejected with identity_rejected. Rotating the identity secret (app settings, or POST /v1/apps/:id/rotate-identity-secret) invalidates outstanding tokens; pass unverify: true to also mark existing players as unverified.

Verified only. In the app settings you can require a verified identity before a player can send messages. Unverified players then see the chat but get verification_required when they send.

Verified identity with Steam

On Steam builds, the player is already logged in to Steam. The SDK asks Steam for a Web API ticket with the identity "inngame" and sends it; the Inngame server checks it with Steam (ISteamUserAuth/AuthenticateUserTicket) using your publisher Web API key, and gets the player's SteamID.

  1. Connect Steam in the dashboard (Settings → Apps → your app → Integrations → Steam): your Steam App ID and a publisher Web API key. See Integrations.
  2. In the game, call Inngame.IdentifySteam(getTicketHex). The Unity quickstart has helpers for Steamworks.NET and Facepunch.Steamworks.

Errors: steam_not_configured (step 1 missing) or steam_ticket_rejected.

What happens to history

Logout and deletion

Inngame.Logout() detaches the device: it continues as a new anonymous player and stops receiving that player's push notifications. Inngame.DeleteData() deletes the player, their conversations and photos on the server, then local data. From the API, an admin can do the same with DELETE /v1/users/:id.