Skip to main content
Signals to the native SDK whether the purchase triggered by onPurchaseRequest succeeded or failed. This must be called in every code path of your onPurchaseRequest handler.
This call is mandatory. If you do not call completePurchaseRequest() after receiving an onPurchaseRequest event, the SDK will remain locked and cannot present future offers until the app restarts.

Signature

completePurchaseRequest(success: boolean): Promise<{ success: boolean }>

Parameters

NameTypeDescription
successbooleantrue if the purchase succeeded, false if it failed or was cancelled

Usage

Standard pattern

Encore.onPurchaseRequest(async ({ productId }) => {
  try {
    await billingService.purchase(productId);
    await Encore.completePurchaseRequest(true);
  } catch (error) {
    await Encore.completePurchaseRequest(false);
  }
});

Common mistake — missing failure path

// BAD — if purchase throws, completePurchaseRequest is never called
Encore.onPurchaseRequest(async ({ productId }) => {
  await billingService.purchase(productId);
  await Encore.completePurchaseRequest(true);
  // If purchase() throws, the SDK is locked!
});
// GOOD — always call completePurchaseRequest in both paths
Encore.onPurchaseRequest(async ({ productId }) => {
  try {
    await billingService.purchase(productId);
    await Encore.completePurchaseRequest(true);
  } catch (error) {
    await Encore.completePurchaseRequest(false);
  }
});

Behavior

  • One active request: Only one purchase request is active at a time. Calling completePurchaseRequest() resolves the current request.
  • Idempotent: Calling it when no request is pending returns { success: false } with an error message — it does not throw.
  • Stale cleanup: If a new onPurchaseRequest fires before the previous was completed, the stale request is automatically failed.
On iOS, failing to complete the request keeps the offer sheet coordinator active, preventing future show() calls from presenting. On Android, the purchase coroutine remains suspended indefinitely.