Prerequisites

We recommend using the Sandbox environment for this guide so you can test without processing real payments.

Overview

The Macropay Customer Portal gives your customers a self-service destination to:
  • View and download invoices
  • Manage active subscriptions (upgrade, downgrade, cancel)
  • Access purchased benefits (license keys, file downloads, etc.)
  • View usage-based billing charges
You can direct customers to the hosted portal or embed it in your app.

Step 1: Create a Customer Session Token

To give a customer authenticated access to the portal, generate a session token via the API:
import { Macropay } from "@macropay/sdk";

const macropay = new Macropay({
  accessToken: process.env.MACROPAY_ACCESS_TOKEN!,
  server: "sandbox",
});

const session = await macropay.customerSessions.create({
  customerId: "cust_xxx",
});

// Redirect customer to this URL
console.log("Portal URL:", session.customerPortalUrl);

Step 2: Redirect to the Portal

Simple redirect

Redirect your customer to the customerPortalUrl returned from the session creation:
// src/app/portal/route.ts (Next.js)
import { redirect } from "next/navigation";
import { Macropay } from "@macropay/sdk";

const macropay = new Macropay({
  accessToken: process.env.MACROPAY_ACCESS_TOKEN!,
  server: "sandbox",
});

export async function GET(req: Request) {
  // Look up the Macropay customer ID from your database
  const customerId = await getCustomerIdFromSession(req);

  const session = await macropay.customerSessions.create({
    customerId,
  });

  redirect(session.customerPortalUrl);
}

Using the Next.js adapter

The @macropay/nextjs package provides a shorthand:
// src/app/portal/route.ts
import { CustomerPortal } from "@macropay/nextjs";

export const GET = CustomerPortal({
  accessToken: process.env.MACROPAY_ACCESS_TOKEN!,
  getCustomerId: async (req) => {
    // Return the Macropay customer ID for the authenticated user
    return await getCustomerIdFromSession(req);
  },
  server: "sandbox",
});
Add a link in your app’s navigation:
<a href="/portal">Manage Subscription</a>

Step 3: Embed the Portal (Optional)

For a seamless experience, embed the portal directly in your app using an iframe:
// src/app/account/page.tsx
"use client";

import { useEffect, useState } from "react";

export default function AccountPage() {
  const [portalUrl, setPortalUrl] = useState<string | null>(null);

  useEffect(() => {
    fetch("/api/portal-session")
      .then((res) => res.json())
      .then((data) => setPortalUrl(data.url));
  }, []);

  if (!portalUrl) return <div>Loading...</div>;

  return (
    <iframe
      src={portalUrl}
      style={{ width: "100%", height: "800px", border: "none" }}
      title="Customer Portal"
    />
  );
}
With a supporting API route:
// src/app/api/portal-session/route.ts
import { Macropay } from "@macropay/sdk";

const macropay = new Macropay({
  accessToken: process.env.MACROPAY_ACCESS_TOKEN!,
  server: "sandbox",
});

export async function GET(req: Request) {
  const customerId = await getCustomerIdFromSession(req);

  const session = await macropay.customerSessions.create({
    customerId,
  });

  return Response.json({ url: session.customerPortalUrl });
}

Step 4: Customize Branding

Customize the portal appearance in the Macropay dashboard:
  1. Go to Settings > Branding
  2. Upload your logo
  3. Set your primary brand color
  4. Configure accent colors
The portal will reflect your branding, providing a consistent experience for your customers.

Hosted Portal (No Code Required)

Customers can also access the portal directly without any integration on your part:
https://macropay.com/your-org-slug/portal
They authenticate by entering the email address used during purchase. Macropay sends a magic link to verify their identity.

What’s Next?

Customer Management

Learn about customer records and states

Customer State API

Query customer entitlements from your backend

Benefits

Configure benefits like license keys and file downloads

Subscription Management

Handle subscription upgrades and downgrades