GiftingStack
Sign in Get started

Guide

How to add live-stream gifts to your app

Viewers buy coins, pick a gift, and everyone watching sees it land with a full-screen effect. This guide walks through the whole feature with GiftingStack: the coin balance, the gift tray, the effects, the live room every viewer joins, and battles between hosts. Your video, audio and chat stay exactly where they are; GiftingStack only carries the gifts.

What you are building

1. Create the project and the catalog

Sign up at app.giftingstack.com, create a project, name your currency and add gifts (the test environment is free). Copy a test secret key: it lives only on your server.

2. Sell coins and credit them from your server

Inside an iOS or Android app, coins are sold with the store's in-app purchase. Your server verifies the receipt, then credits the coins. The credit is idempotent and its reference is unique forever, so a retry or a replayed receipt never credits twice.

POST /v1/receipts/verify                 -> { "receipt_id": "rcp_..." }
POST /v1/users/ava/credit
Idempotency-Key: 6f1c...                  (a new UUID per operation)
{ "amount": 500, "reason": "purchase", "reference": "apple_2000000123", "receipt_id": "rcp_..." }

A web checkout credits with price and currency instead, and free coins with "bonus": true. Details: receipt validation.

3. Give the app a client token

The app never holds your secret key. Your server mints a short-lived client token for the signed-in user, with the rooms that user may join:

POST /v1/client-tokens
{ "user": "ava", "name": "Ava", "rooms": ["live_*"] }

4. Show the gift tray and the effects

Web shown; React Native, Flutter, Android and iOS have the same pieces (SDKs).

import { createGiftingClient } from "@giftingstack/sdk";
import { GiftEffectLayer, createGiftTray, joinRoom } from "@giftingstack/sdk/web";

const client = createGiftingClient({
  getToken: async () => (await fetch("/api/gift-token")).text(),
});
const effects = new GiftEffectLayer(streamElement);
const room = joinRoom({ room: "live_123", getToken, client, effects });
const tray = createGiftTray({
  container: streamElement,
  client,
  receiver: stream.hostId,
  roomId: "live_123",
  effects,
  onTopUp: openCoinStore,
});
giftButton.onclick = () => tray.toggle();

Every gift sent into live_123, from this viewer or any other, now plays on every viewer's screen. The SDKs reconnect by themselves and catch up on gifts missed during a short drop.

5. Reward the host your way

Receivers never get spendable coins: a gift moves coins from the sender to nobody, and the receiver's received-gifts counter goes up. Your server gets a gift.sent webhook and decides what a gift is worth to the host in your app (points, a rank, a revenue share you run yourself). See webhooks.

6. Add battles

POST /v1/rooms/live_123/battle
{ "round": "match_42_r1", "receivers": ["ava", "mateo"], "duration_s": 300 }

Viewers pick a side by choosing the receiver of their gift; the SDK draws the score bar.

How big can a room get?

Live rooms hold up to 1,000 viewers on Starter, 5,000 on Growth and 20,000 on Scale, and more on Enterprise. Rooms spread over shards by themselves; GiftingStack has been load-tested at 250,000 viewers in one room and at 200 gifts a second to 40,000 viewers, with gifts on screen in under a second.

Next steps