Search documentation

Find pages, sections, and content across all docs.

WavedashDocs

Player identity

Authentication, friends, avatars, and presence

Players sign in on Wavedash before they launch your game. The injected SDK receives credentials from the host page and attaches them to each API call. You never embed login UI inside the game.

Presence is currently available in the JavaScript SDK only. The Godot and Unity bindings do not expose presence methods yet.

Reading the current player

func print_player():
    var user = WavedashSDK.get_user()
    var user_id = WavedashSDK.get_user_id()
    var username = WavedashSDK.get_username()
    print(user_id, " ", username, " ", user)
void PrintPlayer()
{
    var userId = Wavedash.SDK.GetUserId();
    var user = Wavedash.SDK.GetUser();
    Debug.Log($"{userId} {user?["username"]}");
}
const user = Wavedash.getUser();
const userId = Wavedash.getUserId();
const username = Wavedash.getUsername();
console.log(userId, username, user);
MethodReturns
getUser()Full profile object for the signed-in player
getUserId()Stable string ID
getUsername()Display name

Looking up other players

getUsername(userId) returns the display name of any player your game has seen — a friend from listFriends(), or a lobby peer. It returns null for unknown users, so call listFriends() once on startup to populate the cache.

var name = WavedashSDK.get_username(peer_user_id)
string name = Wavedash.SDK.GetUsername(peerUserId);
const name = Wavedash.getUsername(peerUserId);

Gameplay tokens

Gameplay tokens are game-scoped and short-lived. Wavedash issues them when the session starts and the SDK attaches them to all API calls. When a token nears expiry, the SDK requests a fresh one. You do not read or store these tokens in normal game code.

Treat gameplay tokens as secrets at runtime. Do not log them or send them to your own servers unless you control the receiving endpoint.

Fetching the JWT explicitly

If you operate your own backend and want to authenticate the player using their Wavedash identity, call getUserJwt() to get a signed JWT you can forward to your server and verify there. The SDK returns a cached token when possible and refreshes it on demand.

func send_to_my_backend():
    var response = await WavedashSDK.get_user_jwt()
    if not response.success:
        return
    var jwt = response.data
    # forward `jwt` to your own server in the Authorization header
async void SendToMyBackend()
{
    string jwt = await Wavedash.SDK.GetUserJwt();
    if (string.IsNullOrEmpty(jwt))
        return;
    // forward `jwt` to your own server in the Authorization header
}
const response = await Wavedash.getUserJwt();
if (response.success) {
  const jwt = response.data;
  // forward `jwt` to your own server in the Authorization header
}

Verify the JWT on your backend against the Wavedash public keys. The token is short-lived (1 hour); call getUserJwt() again if a previous token has expired.

Verifying the JWT on your backend

Tokens are signed with RS256 and the public keys are published at https://auth.wavedash.com/.well-known/jwks.json. Use any JWKS-aware library to verify — the following example uses jose in Node.js:

import { createRemoteJWKSet, jwtVerify } from "jose";

const JWKS = createRemoteJWKSet(
  new URL("https://auth.wavedash.com/.well-known/jwks.json")
);

export async function verifyWavedashJwt(token: string) {
  const { payload } = await jwtVerify(token, JWKS, {
    issuer: "https://auth.wavedash.com",
    audience: "gameplay.wavedash.com"
  });
  return payload;
}

async function getVerifiedWavedashUserId(jwt: string) {
    const payload = await verifyWavedashJwt(jwt);
    const userId = payload.sub;
    reutrn userId;
}

A verified gameplay JWT payload looks like:

interface GameplayJwtPayload {
  sub: string;    // Wavedash user ID — use this as the player's identity
  iss: "https://auth.wavedash.com";
  aud: "gameplay.wavedash.com";
  scope: "gameplay";
  gbid: string;     // game build ID
  gcid: string;     // game cloud ID (differentiates playtest from production)
  iat: number;      // issued-at (seconds since epoch)
  nbf: number;      // not-before (seconds since epoch)
  exp: number;      // expiry (seconds since epoch)
}

Use payload.sub as the stable user ID for your own records. Reject the token if jwtVerify throws an error — it handles signature, issuer, audience, and expiry checks for you.

Wavedash loads your game in a cross-origin-isolated context, so any HTTP response your backend sends to the game must include Cross-Origin-Resource-Policy: cross-origin and Access-Control-Allow-Origin: *, or the browser will block it. WebSockets are unaffected — if you check the Origin header, just confirm the host ends with .builds.wavedash.com.

Friends

The Friends API lets you retrieve the current player's friends list and display user avatars.

Listing friends

func _ready():
    WavedashSDK.got_friends.connect(_on_got_friends)

func load_friends():
    WavedashSDK.list_friends()

func _on_got_friends(response):
    if response.get("success", false):
        for friend in response.get("data", []):
            print(friend["username"], " - Online: ", friend["isOnline"])
async void Start()
{
    var friends = await Wavedash.SDK.ListFriends();
    if (friends != null)
    {
        foreach (var friend in friends)
            Debug.Log($"{friend["username"]} - Online: {friend["isOnline"]}");
    }
}
const response = await Wavedash.listFriends();
if (response.success) {
  response.data.forEach(friend => {
    console.log(`${friend.username} - Online: ${friend.isOnline}`);
  });
}

Friend data

FieldTypeDescription
userIdId<"users">Friend's user ID
usernamestringDisplay name
avatarUrlstring?URL to avatar (if set)
isOnlinebooleanWhether currently online

User avatars

Get a CDN URL for a user's avatar. Users must be cached (seen via friends list or lobby membership) first.

JS constantNative size constantPixelsUse case
Wavedash.AvatarSize.SMALLWavedashConstants.AVATAR_SIZE_SMALL (Godot) / AvatarSize.SMALL (Unity)64pxLists, compact UI
Wavedash.AvatarSize.MEDIUMWavedashConstants.AVATAR_SIZE_MEDIUM (Godot) / AvatarSize.MEDIUM (Unity)128pxProfile cards, chat
Wavedash.AvatarSize.LARGEWavedashConstants.AVATAR_SIZE_LARGE (Godot) / AvatarSize.LARGE (Unity)256pxFull profile view
# Just the URL — cheap, synchronous
var url = WavedashSDK.get_user_avatar_url(user_id, WavedashConstants.AVATAR_SIZE_MEDIUM)

# Or: async helper that fetches + decodes to a Texture2D and emits a signal
func _ready():
    WavedashSDK.user_avatar_loaded.connect(_on_avatar_loaded)

func load_friend_avatar(user_id: String):
    WavedashSDK.get_user_avatar(user_id, WavedashConstants.AVATAR_SIZE_MEDIUM)

func _on_avatar_loaded(texture: Texture2D, user_id: String):
    if texture:
        $AvatarSprite.texture = texture
// Just the URL — cheap, synchronous
string url = Wavedash.SDK.GetUserAvatarUrl(userId, WavedashConstants.AvatarSize.MEDIUM);

// Or: async helper that fetches + decodes to a Texture2D
public async void LoadFriendAvatar(string userId)
{
    var texture = await Wavedash.SDK.GetUserAvatar(userId, WavedashConstants.AvatarSize.MEDIUM);
    if (texture != null)
        avatarImage.texture = texture;
}
const url = Wavedash.getUserAvatarUrl(userId, Wavedash.AvatarSize.MEDIUM);
if (url) {
  const img = new Image();
  img.src = url;
}

If getUserAvatarUrl() / GetUserAvatarUrl() / get_user_avatar_url() returns null, the user has not been cached yet or has no avatar set. Call listFriends() early to populate the cache.

Presence

The Presence API lets you share player status and activity with friends. Use it to show what players are doing and enable "join game" functionality.

The updateUserPresence method accepts an arbitrary data object — the SDK does not enforce a schema, so you can include any keys that are meaningful for your game. Common conventions include status, details, and lobbyId.

# Presence is not yet available in the Godot SDK.
// Presence is not yet available in the Unity SDK.
await Wavedash.updateUserPresence({
  status: "In Game",
  details: "Playing Level 5",
  level: 5,
  score: 12500,
  lobbyId: "lobby_abc123"
});

Joinable games

Include a lobbyId in presence data to enable "Join Game" functionality on the platform:

await Wavedash.updateUserPresence({
  status: "In Lobby",
  details: "Arena - Waiting",
  lobbyId: lobbyId,
  canJoin: lobbyUsers.length < maxPlayers
});

Clearing presence

await Wavedash.updateUserPresence({});