PlaySuper LogoPlaySuper
Unity SDK

Touchpoints & Curated Lists

Fetch and display reward widgets, product collections, and promotional content in your Unity game

Beyond the built-in store, you can render reward widgets and product collections directly in your game UI using touchpoints and curated lists.

Touchpoints 2.0

Needs PlaySuper Unity SDK 4.5.0 or later, published to OpenUPM on 18 September 2026. TouchpointV2Manager does not exist in 4.4.0, so the code on this page will not compile against it. Check your version in Packages/manifest.json or in Window > Package Manager > PlaySuper, and upgrade with openupm add com.playsuper.unity@4.5.0.

On 4.5.0 exactly, read the call-to-action from tp.item.cta rather than tp.cta — the typed model in that release carries it on the item. The API sends it in both places, so either works today and tp.cta is the one to keep.

You can also call the endpoint directly from Unity or your backend:

GET https://api.playsuper.club/v2/touchpoints/serve?screen=home
x-api-key: YOUR_API_KEY

The request and response are documented in the Touchpoints API Reference. It is the same endpoint this manager wraps; you lose the typed model and OpenCta's attribution handling, nothing else.

TouchpointV2Manager and TouchpointManager are different systems, despite the similar names. The TouchpointManager methods further down are the older node-based touchpoints: they take a coinId and return a different shape. Upgrading to 4.5.0 changes nothing about them, and nothing migrates on its own — an existing integration keeps working untouched until you port it deliberately.

A touchpoint is an offer the studio places on one of their game's screens from the PlaySuper console (your game's Integration page in the Testing environment; see Console Setup) or through the PlaySuper for Claude connector. The game names the screen it is about to show; the server returns the artwork the studio chose and one concrete offer already composed into it — priced for this player, with the coin maths done. Your game draws two images and opens a URL.

Fetching a touchpoint

using PlaySuperUnity;

async void ShowHome()
{
    var tp = await TouchpointV2Manager.Serve(TouchpointV2Manager.Screens.Home);

    if (tp != null && tp.HasTouchpoint)
    {
        // tp.FrameImageUrl  — the frame the studio picked
        // tp.OfferImageUrl  — the offer art, drawn in its centre
        // tp.cta.label — the button copy (also on tp.item.cta for SDK 4.5.0)
        ShowTouchpoint(tp);
    }
}

"Nothing to show" is not an error. A non-null result with HasTouchpoint false means the studio has not configured this screen, or has but no catalogue item is available right now. Both are ordinary states and the call succeeded. Only null means the request itself failed. Treat an unconfigured screen as normal and render without a touchpoint.

asset and item are always both present or both absent — a frame with an empty centre reads as a broken build — so HasTouchpoint is a single check rather than two.

Opening the offer

TouchpointV2Manager.OpenCta(tp);

Pass the response rather than building a URL. The server has already appended campaign attribution to cta.url, and OpenStore reads it back off — a hand-built URL silently loses attribution for every touchpoint your game opens.

Parameters

ParameterTypeDescription
screenstringWhich screen is about to be shown. See TouchpointV2Manager.Screens. Only home is live today; an unrecognised screen returns a 400 naming the valid ones.
typestringOptional. product, coupon or gift-card. Needed only when the screen has more than one placement — an ambiguous call is rejected rather than picked for you.
utmSource / utmMedium / utmCampaignstringOptional. Appended to the CTA URL.
await TouchpointV2Manager.Serve(
    TouchpointV2Manager.Screens.Home,
    TouchpointV2Manager.ItemType.Product,
    utmSource: "level_end");

Response

public class TouchpointV2Response
{
    public string screen;
    public string placementId;          // null when no placement is configured
    public TouchpointV2Asset asset;     // the frame
    public TouchpointV2Item item;       // the offer inside it
    public string servedAt;

    public bool HasTouchpoint { get; }  // asset != null && item != null
    public string FrameImageUrl { get; }
    public string OfferImageUrl { get; }
    public bool IsPortrait { get; }
}
FieldNotes
asset.imageUrlThe frame you draw. Not assetUrl.
asset.orientationPORTRAIT or LANDSCAPE.
item.imageUrlThe offer art, drawn in the frame's centre.
item.pricingcurrency, mrp, price, priceAfterCoins, discountPct. Null for coupons — prices are nested here, not on item itself.
item.offerTextPre-formatted coupon line, e.g. "Flat 40% off up to ₹200". Display as given.
item.coinscoinsRequired and coinDiscount. Null when this game's coin cannot be spent on the item.
ctalabel and url, at the response level — not on item — because a static touchpoint has no item to carry it. Hand the whole response to OpenCta rather than using the URL directly. Also mirrored on item.cta for SDK 4.5.0, which reads it there; new code should use tp.cta.

Every figure is computed server-side for this player and this game's coin. The game does no pricing arithmetic.

Touchpoints

Touchpoints are visual widget configurations that control how rewards and promotions appear in your game. Use the TouchpointManager to fetch touchpoint data and render custom widgets.

This is the original node-based API, and it is still supported. New integrations should prefer Touchpoints 2.0 above, where the server composes the widget for you instead of returning a node tree to walk.

Fetching touchpoints

// Fetch by name (recommended for most use cases)
TouchpointResponse store = await TouchpointManager.GetTouchpointByName("flash-sale-card", "coin-uuid-abcd");

// Fetch by ID
TouchpointResponse offer = await TouchpointManager.GetTouchpointById(
    "6f9a5737-0247-4a71-89eb-b5d02212f179",
    "coin-uuid-abcd"
);

// List all active touchpoints
TouchpointListResponse list = await TouchpointManager.ListTouchpoints("coin-uuid-abcd");

Processing touchpoint data

if (store?.nodes?.Length > 0)
{
    TouchpointNode node = store.nodes[0];

    Debug.Log($"Layout: {node.layoutHint}");

    string bgImage = node.background?.images?[0];
    string titleText = node.title?[0]?.text;
    string titleColor = node.title?[0]?.color;
    string ctaAction = node.cta?.action;
    string ctaText = node.cta?.text;

    bool timerEnabled = node.GetStyleHint<bool>("timerEnabled", false);

    if (node.HasReward)
    {
        HydratedReward reward = node.GetReward();
        string brandName = reward?.brandName;
    }
}

For the full data model, example responses, what dataType, layoutHint and cta.action mean, and how these touchpoints are created for your game, see the Touchpoints API Reference.

Curated lists

Curated lists are pre-configured collections of products or rewards set up by PlaySuper. Fetch them by name and display them in your game's UI.

Fetching a curated list

// Products
var products = await PlaySuperUnitySDK.Instance.GetCuratedList(
    CuratedListType.Products,
    "homepage_featured",
    "your-coin-id"
);

// Rewards
var rewards = await PlaySuperUnitySDK.Instance.GetCuratedList(
    CuratedListType.Rewards,
    "daily_deals",
    "your-coin-id"
);
ParameterTypeRequiredDescription
typeCuratedListTypeYesCuratedListType.Products or .Rewards
listNamestringYesName of the curated list (provided by PlaySuper)
coinIdstringYesYour game's coin ID
versionstringNoAPI version for rewards (e.g., "2.0.0")

Working with products

public async void LoadFeaturedProducts()
{
    try
    {
        var response = await PlaySuperUnitySDK.Instance.GetCuratedList(
            CuratedListType.Products,
            "homepage_featured",
            "your-coin-id"
        );

        foreach (var product in response.products)
        {
            Debug.Log($"Product: {product.name}");
            Debug.Log($"Brand: {product.brandName}");
            Debug.Log($"Image: {product.imageUrl}");

            var sku = product.skus[0];
            if (sku.playSuperPrice != null)
            {
                Debug.Log($"Price: {sku.playSuperPrice.discountedListingPrice}");
            }
        }
    }
    catch (Exception ex)
    {
        Debug.LogError($"Failed to load products: {ex.Message}");
    }
}

Key product fields:

FieldDescription
nameProduct display name
brandNameBrand name
imageUrlPrimary product image
imagesAdditional product images
descriptionHTML description
plainTextDescriptionPlain text description
skusAvailable variants with pricing
optionTypesProduct options (size, color, etc.)
ctaUrlDeep link to view/purchase in store

SKU pricing (sku.playSuperPrice):

FieldDescription
listingPriceOriginal price
discountedListingPriceFinal price after discount
discountPercentDiscount percentage

Working with rewards

public async void LoadRewards()
{
    try
    {
        var response = await PlaySuperUnitySDK.Instance.GetCuratedList(
            CuratedListType.Rewards,
            "gift_cards",
            "your-coin-id"
        );

        foreach (var reward in response.rewards)
        {
            Debug.Log($"Title: {reward.metadata.campaignTitle}");
            Debug.Log($"Brand: {reward.brandName}");
            Debug.Log($"Image: {reward.metadata.campaignCoverImage}");

            if (reward.price.Count > 0)
            {
                Debug.Log($"Price: {reward.price[0].amount} coins");
            }

            Debug.Log($"Available: {reward.inventory.availableQuantity}");
        }
    }
    catch (Exception ex)
    {
        Debug.LogError($"Failed to load rewards: {ex.Message}");
    }
}

Key reward fields:

FieldDescription
brandNameBrand name
metadata.campaignTitleReward title
metadata.campaignSubTitleReward subtitle
metadata.campaignCoverImageCover image URL
metadata.brandLogoImageBrand logo URL
metadata.termsAndConditionsTerms and conditions
metadata.howToRedeemRedemption instructions
price[0].amountPrice in coins
inventory.availableQuantityStock remaining
ctaUrlDeep link to store page

Deep-linking to a product or reward

Both products and rewards include a ctaUrl that opens the store directly to that item:

PlaySuperUnitySDK.Instance.OpenStore(product.ctaUrl);
PlaySuperUnitySDK.Instance.OpenStore(reward.ctaUrl);

// With UTM tracking
PlaySuperUnitySDK.Instance.OpenStore(product.ctaUrl, "featured_banner");

Contact your PlaySuper integration team to get curated list names and configure custom lists for your game.

Next, see the Complete Example for a full integration script, offline support, user properties, and troubleshooting.