1

Create Subscription Intent (Merchant Server → xPay Server)

From your backend, call the Create Subscription API to initialize the subscription.
The response contains subscriptionId and fwdUrl.
See Create Subscription API for details.
Set callbackUrl to a client page that can read the redirect parameters and show a result screen.
2

Store Identifiers (xPay Server → Merchant Server)

Save the subscriptionId along with any correlation IDs.
This ensures you can reconcile webhook notifications with customer sessions.
Store only the minimal customer metadata required to render the post-checkout page.
3

Send Data to Frontend (Merchant Server → Merchant Frontend)

Return the fwdUrl and subscription details to the frontend so the customer can start the checkout flow.
Ensure the page is ready to handle navigation and the redirect to your callbackUrl.
4

Redirect to xPay Checkout (Merchant Frontend → xPay Client)

Use the fwdUrl to redirect customers to xPay’s subscription checkout page.
const redirectToSubscriptionCheckout = () => {
  const url = new URL(fwdUrl); // fwdUrl received from your server
  window.open(url.href).focus();
};
5

Receive Webhook Result (xPay Server → Merchant Server)

After checkout, xPay sends a webhook to your backend with the final outcome:
  • subscription.active for successful subscription creation
  • The webhook payload includes subscriptionId and other relevant subscription details.
Always treat the webhook as the source of truth.
Make your webhook handler idempotent and validate the signature.
6

Handle Customer Redirect (xPay Client → Merchant Frontend)

In parallel, the customer is redirected to your callbackUrl with subscription_id in the query string.
The frontend should display the result page using the status already received via webhook.
const onSubscriptionPageLoad = async () => {
  const url = new URL(window.location.href);
  const subscriptionId = url.searchParams.get("subscription_id");

  // Query your own backend which has stored the webhook result
  const res = await fetch(`/subscription-status?subscription_id=${subscriptionId}`, { credentials: "include" });
  const { status } = await res.json();

  if (["ACTIVE", "TRIALING"].includes(status)) {
    // show subscription success UI
  } else {
    // show failure UI
  }
};

By following this flow, subscription confirmation is handled via webhooks on your backend,
while the redirect ensures a smooth experience for customers.