Skip to main content

Embed a launched game

Your backend calls POST /launch, verifies the signed response and the agreed allowed HTTPS origin, then returns data.url to your already authenticated frontend. Use the complete URL exactly as returned. Its path and token format are implementation details; do not construct a game URL or append your secret, player ID, balance or session yourself.

Browser example​

This HTML expects your own same-origin /api/moonshot/launch endpoint to return { "url": "<verified Moonshot data.url>" }. That route authenticates the player, checks session ownership and CSRF protection, and signs the provider call on the server. It is an operator route you implement, not a Moonshot API endpoint.

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Moonshot game</title>
<style>
html, body { margin: 0; height: 100%; }
#game { display: block; width: 100%; height: 100dvh; border: 0; }
</style>
<body>
<p id="status" role="status">Loading game…</p>
<iframe id="game" title="Moonshot game" allow="fullscreen; autoplay"
referrerpolicy="no-referrer" allowfullscreen hidden></iframe>
<script type="module">
const status = document.querySelector('#status');
const frame = document.querySelector('#game');

try {
const response = await fetch('/api/moonshot/launch', {
method: 'POST',
credentials: 'same-origin',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ gameSlug: 'crash' }),
});

if (!response.ok) {
throw new Error('Launch failed');
}

const { url } = await response.json();
frame.src = url;
frame.hidden = false;
status.hidden = true;
} catch {
status.textContent = 'Unable to launch the game. Please try again.';
}
</script>
</body>
</html>

Create one fresh launch per explicit play/reload action. Avoid framework effects that create multiple launches during one render. Do not automatically retry the same launch request after a timeout.

Browser configuration​

  • Give the iframe and its parent explicit dimensions; height="100%" alone is insufficient if the parent has no height. Check small mobile viewports and rotation.
  • Permit the agreed game origins in your page's CSP frame-src. If the game reports a frame-ancestors or X-Frame-Options error, provide Moonshot the exact embedding origin for configuration. Do not disable browser security to bypass it.
  • Use HTTPS. Preserve the launch URL's query parameters through routers and proxies.
  • Autoplay may require a player interaction. Test audio and fullscreen with browser controls and permissions enabled.
  • Do not add an iframe sandbox policy without agreeing and testing its required permissions. A restrictive policy can block game scripts, storage or navigation.
  • Do not rely on undocumented postMessage events. If you use an agreed event, validate both event.origin and event.source === frame.contentWindow.

If the frame stays blank, see Troubleshooting.