API v1

Integration Guide

Everything you need to integrate Scrollo's video-slot engine into your casino platform. Two API calls to go live.

# Overview

Scrollo exposes a simple REST API with two endpoints your platform calls directly, plus a callback contract where we call you for wallet operations.

1
List Games — fetch the catalogue of available game topics to display in your lobby.
2
Init Session — start a session and get an iframe URL to embed.
3
Handle Callbacks — process balance, bet, win, and refund events on your side.

# Quick Start

TL;DR for Developers
  1. Obtain API credentials from our team
  2. GET /v1/games — list available game topics for your lobby
  3. POST /v1/games/init — start a session, receive an iframe URL
  4. Embed the iframe in your frontend
  5. Handle 4 callbacks on your server: balance, bet, win, refund
  6. Ship it

# Authentication

All requests to the Scrollo API must include your API key in the request header.

Credential Purpose Provided By
API_KEY Authenticates your init and game-listing requests Scrollo (contact us)
CALLBACK_URL Your HTTPS endpoint that receives wallet events You provide during onboarding
CALLBACK_API_KEY Included as x-api-key header in our callbacks to you You provide during onboarding

# List Games

Retrieve the full catalogue of available game topics. Each game represents a themed video collection (e.g. luxury lifestyle, cars, cats) that players can choose from in your lobby.

GET https://api.scrollo.win/v1/games
cURL
curl https://api.scrollo.win/v1/games \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
Response — 200 OK
{
  "games": [
    {
      "uuid": "luxury",
      "name": "💎 Luxury Lifestyle",
      "description": null,
      "media_tag": "luxury",
      "thumbnail_url": "https://scrollo.fra1.digitaloceanspaces.com/thumbnails/games/luxury.jpg",
      "video_count": 39
    },
    {
      "uuid": "cars",
      "name": "🏎️ Luxury Cars",
      "description": null,
      "media_tag": "cars",
      "thumbnail_url": "https://scrollo.fra1.digitaloceanspaces.com/thumbnails/games/cars.avif",
      "video_count": 12
    }
  ]
}

Response fields

Field Type Description
uuid string Unique game identifier — pass this as game_uuid when initializing a session
name string Display name for the game topic
description string | null Optional description text
media_tag string Internal content tag used to categorize the video pool
thumbnail_url string | null URL to a preview image — use this in your lobby cards
video_count number Number of videos currently in this topic's pool
Building your lobby

Use this endpoint to dynamically populate your games lobby. Each game is a themed content category — display them as selectable cards using the thumbnail_url and name fields. When a player picks a game, pass its uuid to the session init endpoint.

# Initialize Session

Start a new game session when a player selects a game. You receive an iframe URL to embed directly in your frontend.

POST https://api.scrollo.win/v1/games/init
Request body
{
  "session_id": "your_unique_session_id",
  "player_id": "your_player_id",
  "currency": "USD",
  "game_uuid": "luxury"
}

Request fields

Field Type Required Description
session_id string Yes Your unique session identifier
player_id string Yes Your internal player identifier
currency string Yes ISO 4217 currency code (e.g. USD, EUR)
game_uuid string Yes Game identifier from the /v1/games listing
Response — 200 OK
{
  "iframe_url": "https://api.scrollo.win/embed?token=...",
  "token": "eyJhbGciOiJIUzI1NiIs..."
}

# Embed the Game

Drop the returned iframe_url into a standard iframe. The game handles its own UI, sound, and fullscreen.

HTML
<iframe
  src="{iframe_url}"
  width="100%"
  height="100%"
  frameborder="0"
  allow="autoplay; fullscreen"
></iframe>

# Callback Events

Scrollo sends HTTP POST requests to your CALLBACK_URL for all wallet operations. Every request includes the x-api-key header set to your CALLBACK_API_KEY. This is the critical integration point.

CALLBACK Balance Inquiry

Scrollo requests the player's current balance before displaying the game and before each round.

Request to your server
{
  "event": "balance",
  "session_id": "your_session_id",
  "player_id": "your_player_id"
}
Expected response
{
  "success": true,
  "balance_cents": 50000
}

CALLBACK Bet Transaction

Player placed a bet. Debit the amount from their wallet.

Request to your server
{
  "event": "bet",
  "session_id": "your_session_id",
  "player_id": "your_player_id",
  "transaction_id": "txn_bet_abc123",
  "amount": 1000,
  "currency": "USD"
}
Expected response
{
  "success": true
}

CALLBACK Win Transaction

Player won the round. Credit the winnings to their wallet.

Request to your server
{
  "event": "win",
  "session_id": "your_session_id",
  "player_id": "your_player_id",
  "transaction_id": "txn_win_def456",
  "amount": 2500,
  "currency": "USD"
}
Expected response
{
  "success": true
}

CALLBACK Refund Transaction

Round was cancelled (player skipped the video or timeout occurred). Credit the original bet amount back.

Request to your server
{
  "event": "refund",
  "session_id": "your_session_id",
  "player_id": "your_player_id",
  "transaction_id": "txn_refund_ghi789",
  "amount": 1000,
  "currency": "USD"
}
Expected response
{
  "success": true
}

# Idempotency

Important

Every transaction includes a unique transaction_id. Your callback handler must be idempotent — if you receive a duplicate transaction_id, return {"success": true} without processing the transaction again. Network retries will cause duplicate deliveries; your system must handle this gracefully.

# Reference Implementation

A minimal Node.js / Express server implementing the full callback contract:

callback-server.js
import express from "express";

const app = express();
const CALLBACK_API_KEY = process.env.SCROLLO_CALLBACK_KEY;
const processedTransactions = new Set();

app.use(express.json());

app.post("/api/scrollo/callback", async (req, res) => {
  // 1. Authenticate
  if (req.headers["x-api-key"] !== CALLBACK_API_KEY) {
    return res.status(401).json({ success: false });
  }

  const { event, player_id, transaction_id, amount } = req.body;

  switch (event) {
    case "balance":
      const balance = await getPlayerBalance(player_id);
      return res.json({ success: true, balance_cents: balance });

    case "bet":
      if (processedTransactions.has(transaction_id)) {
        return res.json({ success: true }); // idempotent
      }
      await debitPlayer(player_id, amount);
      processedTransactions.add(transaction_id);
      return res.json({ success: true });

    case "win":
    case "refund":
      if (processedTransactions.has(transaction_id)) {
        return res.json({ success: true }); // idempotent
      }
      await creditPlayer(player_id, amount);
      processedTransactions.add(transaction_id);
      return res.json({ success: true });
  }
});

app.listen(3000);

# Support