Skip to main content
The SDK surfaces three types of failure: initialization failures, reward delivery failures, and maintenance mode. Each requires a different response. The guiding principle is the same in all cases: never let a ZBD failure break your game.

Initialization failures

Init can fail for several reasons. Always call ShowModal() when init fails. The modal explains the reason to the player and provides a retry path. Never silently fail.
ZBDController.Instance.Init(completion =>
{
    if (completion.success)
    {
        // SDK ready, proceed normally
    }
    else if (completion.maintenance)
    {
        // See Maintenance Mode section below
    }
    else
    {
        // Init failed, show modal so the player can see why and retry
        ZBDModalController.Instance.ShowModal();
        Debug.LogWarning("ZBD init failed: " + completion.error);
    }
});

Common init failure causes

CauseWhat happensWhat to do
VPN or proxy detectedcompletion.success = falseCall ShowModal(). The modal tells the player their VPN was detected and gives them a retry path.
No network connectioncompletion.success = falseCall ShowModal(). The modal surfaces a retry option. Do not prevent gameplay.
Unsupported regioncompletion.success = falseCall ShowModal(). Do not show rewards-related UI. See Global Support.
Attestation failurecompletion.success = falseCall ShowModal(). Indicates a potentially modified device or app.
ZBD maintenancecompletion.maintenance = trueSee Maintenance Mode below.
Do not tie SDK initialization to any core gameplay logic. If Init fails, the game must continue working normally. Players who cannot earn rewards should not be blocked from playing.

Maintenance mode

The ZBD platform occasionally enters maintenance mode. This is surfaced as a maintenance flag on SDK responses. It is not an error.
public class ZBDInitResponse
{
    public bool success;
    public bool maintenance;
    public string userId;
    public string error;
    public string type;
}
Maintenance mode can begin at any time, including mid-session. Handle it on every SDK response, not just during initialization.
ScenarioCorrect behavior
Init returns maintenance = trueIf the player has not started earning yet: hide all rewards-related UI and do not mention ZBD. If the player has already been earning: surface a message that rewards are temporarily unavailable.
SendReward returns maintenance = trueSilently skip the reward. Do not show an error to the player.
GetBalance returns maintenance = trueDo not update the displayed balance. Retry when the next natural trigger occurs.
Maintenance periods are temporary. Do not log them as errors or alert your on-call. They are expected operational events.

Reward delivery failures

Reward delivery can fail independently of initialization. The most common causes are network interruptions and maintenance mode.
ZBDController.Instance.SendReward(amount, completion =>
{
    if (completion.success)
    {
        // Reward delivered, update UI
    }
    else if (completion.maintenance)
    {
        // Silently skip, do not surface to player
    }
    else
    {
        // Delivery failed, silently skip and optionally log
        Debug.LogWarning("Reward delivery failed: " + completion.error);
    }
});
Do not show reward failure messages to players. A failed reward is invisible to the player. The gameplay moment should feel the same whether the reward was delivered or not.

Full error scenario matrix

ScenarioSDK responseCorrect behavior
Init — VPN detectedsuccess = falseShowModal(). Game continues.
Init — no networksuccess = falseShowModal(). Game continues.
Init — unsupported regionsuccess = falseShowModal(). Hide rewards UI.
Init — maintenancemaintenance = trueHide rewards UI for new players. Message existing earners.
Init — attestation failuresuccess = falseShowModal(). Game continues.
App backgrounded mid-rewardn/aHandle gracefully on foreground return. Do not retry automatically.
No internet during reward triggersuccess = falseSkip or queue the reward. Do not crash.
SendReward — maintenancemaintenance = trueSilently skip. No player-facing message.
SendReward — network errorsuccess = falseSilently skip. Log internally.
GetBalance — maintenancemaintenance = trueDo not update balance display.
iOS vs. Android behavior differenceVariesAlways test both platforms separately. SDK behavior can differ between them.

Platform differences

Test iOS and Android separately. The SDK’s attestation behavior, WebView rendering, and modal presentation can differ between platforms in ways that are not always obvious during development. Pay particular attention to:
  • Android back button: Handle the back button to close the modal if it’s open. See Integration.
  • iOS foreground transitions: The modal may need explicit handling when the app returns from background.
  • VPN detection: VPN behavior differs between iOS and Android network stacks. A VPN that passes on one platform may be flagged on the other.