# Manual integration (raw `window.GammaSDK`)

If you can't use the [`@swiftware/gamma-sdk`](./getting-started/install.md) package
(no bundler, or you want zero dependencies), you can call the raw bridge that the
Gamma Games app injects as `window.GammaSDK`. There's no `<script>` tag, no build
step, and no API key — the host injects it automatically when your game runs inside
the app.

> The package is recommended: it wraps everything below in a typed, promise-first
> API and adds the offline fallback and dev mock. Use the raw bridge only if you
> have a reason to.

## Capability detection

The bridge exists **only inside the Gamma Games app**. Always guard:

```js
function hasGammaSDK() {
  return !!(window.GammaSDK && window.GammaSDK.ready);
}

// The SDK may inject before or after your code runs:
if (hasGammaSDK()) {
  start();
} else {
  window.addEventListener('gammasdkready', start);
}
```

## Methods

All methods are **callback-style**; `result` always has a `success` boolean. Each
method is also mirrored under `window.GammaSDK.promises.*` for `async/await`.

```js
// Coins
GammaSDK.getCoins((r) => {/* {success, balance} */});
GammaSDK.spendCoins(50, 'extra_life', (r) => {/* {success, newBalance, spent} | {success:false, error, balance?} */});
GammaSDK.earnCoins(5, 'checkpoint', (r) => {/* {success, newBalance, earned} */});

// Coin value (host ≥ 1.1.0)
GammaSDK.getCoinValue((r) => {/* {success, coinValue: {usdPerCoin, currencyCode, displayName, symbol, iconUrl}} */});

// Progress (keyed on user + game, last-write-wins, ≤100 KB)
GammaSDK.saveProgress({level: 12, schemaVersion: 1}, (r) => {/* {success, sizeBytes} */});
GammaSDK.loadProgress((r) => {/* {success, data} — data may be null */});

// Player (public fields only)
GammaSDK.getPlayer((r) => {/* {success, player: {id, displayName, avatar, frame, isSubscribed}} */});
```

Promise form:

```js
const r = await GammaSDK.promises.spendCoins(30, 'revive');
if (r.success) grantRevive();
```

## Offline fallback

Because the bridge is absent outside the app, keep a `localStorage` path for
progress so the same build still runs elsewhere:

```js
function saveState(state) {
  if (hasGammaSDK()) GammaSDK.saveProgress(state);
  else localStorage.setItem('mygame_save', JSON.stringify(state));
}
```

## Reference constants

```text
Global:          window.GammaSDK
Readiness flag:  window.GammaSDK.ready        // boolean
Ready event:     'gammasdkready' on window
Version:         window.GammaSDK.version      // '1.1.0'

Methods (callback-style; also on window.GammaSDK.promises):
  getCoins(cb)
  spendCoins(amount:int 1..10000, reason:/^[a-z0-9_]+$/, cb)
  earnCoins(amount:int 1..100,    reason:/^[a-z0-9_]+$/, cb)
  saveProgress(data:JSON, cb)      // ≤100 KB encoded
  loadProgress(cb)
  getPlayer(cb)
  getCoinValue(cb)                 // host ≥ 1.1.0
```

See [error codes](./error-codes.md) and [limits & security](./limits-and-security.md)
for the rest of the contract.
