Games

Game SDK

Connect your web game to the Xara app with @xavatech/xara-game-sdk.

The SDK connects your page to the Xara app's game screen. The app makes every call to Xara with the player's own account; your page never sees a token, a PIN, or any account details, and needs no API key.

Install

To start a new game with the SDK, its tests, and the game skill already set up:

npx @xavatech/create-xara-game my-game --name "My Game" --players 2-4

To add the SDK to a page you already have:

npm install @xavatech/xara-game-sdk

Without a bundler, load https://unpkg.com/@xavatech/xara-game-sdk and use the XaraGameSDK global.

To have a coding assistant write the game, install the Xara game skill and describe it.

Connect

import { connect } from "@xavatech/xara-game-sdk";

type Move = { cell: number };
const xara = connect<Move>();

xara.onChange(draw); // someone moved, accepted, or left
draw(await xara.load()); // the game as it is, with every move so far

async function play(cell: number) {
  if (!xara.isMyTurn()) return;
  await xara.move({ cell });
}

Draw your game from state.moves every time. That is how a game reopened later, or opened by someone watching, catches up.

Calls

CallWhat it does
load()Loads the game and resolves with its state.
onChange(listener)Calls listener with each new state. Returns a function that stops it.
isMyTurn()Whether this phone is playing and it is their turn.
accept()Accepts this phone's invite.
move(move, { outcome })Plays this phone's move. With outcome, the move ends the game.
end(outcome)Ends the game without another move.
buy({ item, amount, reference })Asks the player to buy item for amount naira.
close()Closes the game screen.

An outcome is { winners, summary }: the ids of the winners (none for a draw) and an optional line, up to 120 characters, shown under the result on the chat card. Every player reads the same summary, so describe the game rather than a player ("X wins with three in a row"), never "You won"; the card already tells each player whether they won.

Calls the app refuses reject with a XaraGameError. Its code is rejected (the message says why, for example "It's not your turn"), timeout, or closed when the page isn't open in Xara.

Game state

Field
session.statusinvited, active, completed, declined, or cancelled.
session.moveCountHow many moves have been played.
session.turnWhose turn it is, while the game is being played.
session.outcomeHow it ended: winners, summary, and leftBy when a player left.
playersIn turn order, starter first. name is how this phone labels them; you marks this phone.
meThis phone's id, and watching when a group member is only watching.
movesEvery move, oldest first: step, playerId, and move (what the game sent).
purchasesWhat this phone has bought in this game.

Payments

const paid = await xara.buy({
  item: "Hint",
  amount: 100, // whole naira
  reference: `hint-${state.session.id}-${state.session.moveCount}`,
});
if (paid.status === "success") showHint();

The app shows the item, the amount, and your business name, and asks for the player's PIN. The promise resolves once they have decided:

statusMeaning
successPaid. purchase has the purchase, with receipt.
cancelledThe player closed the sheet without paying.
failedIt couldn't be paid; message says why.

reference is your id for the purchase, up to 64 letters, digits, or _.:-. Asking again with the same reference returns that purchase instead of charging again, so derive it from what is being bought. A reference used for a different item or amount is refused. The payment is a transfer to your business's Xara wallet and shows in your transactions.

Build in a browser

The SDK includes a mock app, so you can build without a phone. Outside the app it adds a bar that switches which player's phone the page is, and a move only goes through on that player's turn.

import { connect, inXara, mockApp } from "@xavatech/xara-game-sdk";

if (!inXara()) {
  mockApp({
    players: [
      { id: 1, name: "Ada" },
      { id: 2, name: "Bayo" },
    ],
  });
}

Security

  • The app only answers calls from pages on the origin of your submitted URL, over https, and blocks navigation anywhere else. Keep your game's pages, scripts, and assets on that origin, and don't embed other sites in frames.
  • Each time your page loads, the app gives its top frame a fresh key the SDK sends with every call. Frames inside your page can't read it, so they can't act for the player.
  • Xara never trusts your page for money: purchases are approved by the player with their PIN in the app, and paid only to the business that submitted the game.
Copyright © 2026