Skip to main content
The UniBee Hosted Customer Portal is a secure, user-authenticated interface where your customers can self-manage everything after purchases, including:
  • Viewing current subscriptions and plans
  • Upgrading, downgrading, or cancelling subscriptions
  • Updating payment methods and billing information
  • Viewing invoices and payment history
Compared with the Change Subscription After Purchases (Hosted Mode) page—which focuses mainly on subscription changes—the Customer Portal is a broader, all‑in‑one experience for end users.

When to Use the Customer Portal

Use the Customer Portal when you want to:
  • Provide a single entry point for customers to manage all their billing and subscriptions
  • Avoid building your own “My Account / Billing” UI
  • Offer self-service experiences (change plan, update card, view invoices) after checkout
  • Link to a hosted page from your app’s “Billing” or “Account” menu
If you only need a focused subscription change flow for a single plan, you can still use:
Change Subscription After Purchases (Hosted Mode).

How It Works

The integration pattern is similar to the Subscription Update page:
  1. Your backend calls a Session API to get a Customer Portal URL for a specific user.
  2. Your frontend redirects the user to that URL.
  3. The user completes actions in the hosted Customer Portal.
  4. UniBee redirects the user back to your returnUrl or cancelUrl, and sends relevant Webhooks (e.g. subscription updated, invoice paid).

Generate Customer Portal URL (Session API)

You generate the Customer Portal URL via the Session API: API Endpoint: Get Customer Portal URL
curl --location --request POST "$UniBee_API_Host/merchant/session/customer_portal_url" \
  --header "Authorization: Bearer $UNIBEE_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
    "email": "[email protected]",
    "externalUserId": "your_user_id_123",
    "productId": 1001,
    "planId": 2001,
    "vatCountryCode": "DE",
    "returnUrl": "https://yourdomain.com/portal/success",
    "cancelUrl": "https://yourdomain.com/portal/cancel"
  }'

Request Behavior

  • User identification:
    • If userId is provided, UniBee uses it directly.
    • If userId is 0, UniBee will try externalUserId first, then email.
    • If no user is found, the API returns user not found.
  • Subscription resolution:
    • UniBee will try to find the most relevant subscription for this user (optionally filtered by productId):
      • Prefer the latest active / incomplete / creating subscription.
      • Fallback to the latest subscription record.
    • If a subscription is found, the portal URL will include subscriptionId so the portal can focus on that subscription.
    • If no subscription is found, the portal URL is still valid (without subscriptionId) and the user can start their first purchase from the portal.
  • Return URLs:
    • returnUrl: where the user is redirected after completing actions in the portal.
    • cancelUrl: where the user is redirected if they cancel or close the portal without completing actions.

Redirect the Customer

After calling the Session API from your backend, redirect the user to the returned URL:
// Example: from your backend API handler
const response = await fetch('https://api.unibee.dev/merchant/session/customer_portal_url', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.UNIBEE_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: customerEmail,
    productId: 1001,
    planId: 2001,
    returnUrl: 'https://yourdomain.com/portal/success',
    cancelUrl: 'https://yourdomain.com/portal/cancel',
  }),
});

const { data } = await response.json();
// In your frontend:
window.location.href = data.url; // Redirect to UniBee Customer Portal

Handle Return Callback

After the customer finishes in the Customer Portal, UniBee redirects them back to your returnUrl (or cancelUrl). You can handle the callback similarly to the checkout / subscription update flows:
// Example: handle return from Customer Portal
const urlParams = new URLSearchParams(window.location.search);
const success = urlParams.get('success') === 'true';

if (success) {
  // Refresh user subscriptions / invoices from your backend
  await refreshBillingData();
  showNotification('Billing information updated successfully!');
} else {
  // Optional: handle cancel case
  showNotification('Customer Portal was closed without changes.');
}
In addition, you should listen to corresponding Webhooks such as:
  • subscription.update.success
  • subscription.pending_update.success
  • invoice.paid
so your system can react to changes even if the frontend callback is interrupted.