> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# The Hosted Subscription Management Page

> How /subscription/manage works: which statuses return a link and why you get A0028, how long a link lasts and whether a new one kills the old, exactly what the customer can see and do on the page, how far it can be branded, and why cancellation there is immediate.

Waffo hosts a page where your customer can see their own subscription, manage the
payment methods on it, and cancel it. You get the URL from
`/api/v1/subscription/manage` and send the customer there. Emails Waffo sends
your customers can link to it too — see
[Subscription emails to your customers](/docs/en/support/subscription-notifications-faq).

## Which subscriptions can I get a management link for?

Anything that has actually existed as a live subscription — including ones that
have already ended:

| Subscription status | `/subscription/manage` |
| - | - |
| `ACTIVE` | Returns a link |
| `MERCHANT_CANCELLED`, `USER_CANCELLED`, `CHANNEL_CANCELLED`, `PLATFORM_CANCELLED` | Returns a link |
| `EXPIRED` | Returns a link |
| `IN_PROGRESS` | Rejected — `A0028` |
| `AUTHORIZATION_REQUIRED` | Rejected — `A0028` |
| `CLOSE` | Rejected — `A0028` |

## What does `A0028` mean?

> `A0028` — Subscription is still in progress or has failed and management url is
> not available

It means the subscription never became live: the customer has not finished
confirming it, has not authorised the mandate yet, or the subscription closed
before it ever activated. There is nothing to manage, so no link is minted.

It is **not** a permissions or configuration error, and retrying will not help
while the status is unchanged. What to do instead:

* `IN_PROGRESS` / `AUTHORIZATION_REQUIRED` — the customer still owes you an
  authorisation. Send them to `subscriptionAction.webUrl` from the creation
  response, not to a management link.
* `CLOSE` — the subscription is dead and cannot be revived. Create a new one.

## Can a cancelled or expired subscription still be opened?

Yes, and that is deliberate. The customer can still see the plan and their
billing history — which is usually exactly what they want after cancelling.

What they cannot do there is act on it: payment-method changes are rejected on
any subscription that is not `ACTIVE`, and there is nothing left to cancel. So a
terminated subscription's page is a read-only receipt, not a re-subscribe entry
point. If a returning customer wants the plan back, that is a new subscription
through `/api/v1/subscription/create`.

## How long does a link last, and does a new one kill the old one?

Each call to `/api/v1/subscription/manage` mints a **new, independent** link.
Every link carries its own expiry, and the response tells you what it is:

| Response field | Use |
| - | - |
| `managementUrl` | The link to send the customer |
| `expiredAt` | That link's expiry, ISO 8601, UTC |
| `subscriptionStatus` | The subscription's status at the moment the link was minted |

Consequences worth designing around:

* **Minting a new link does not invalidate earlier ones.** Two links issued
  minutes apart both work until each one's own `expiredAt` passes. Do not rely on
  re-calling `manage` to revoke a link you already sent.
* **Read `expiredAt`; do not hardcode a lifetime.** The window is short and is
  configuration, not a contract. A link is a hand-off, not a bookmark: mint it at
  the moment the customer clicks through, rather than storing one and mailing it
  later.
* Calling `manage` repeatedly is fine — it has no side effect on the
  subscription.

Links Waffo puts inside its **own** customer emails behave differently: they last
substantially longer, but each new email carries a freshness marker that
**supersedes the links in earlier emails**. So a customer digging out last
month's email may find that link dead while the newest email works. That
supersession applies only among emailed links; it never affects a link you
minted through the API.

## Can Waffo's emails point at my own management page instead?

Yes. Whether the management link in Waffo's customer emails points at **Waffo's
hosted page** or at the **URL you supplied** is a per-account setting:

| Setting | Emails link to |
| - | - |
| Waffo's page (default) | The hosted page, with a freshly minted link |
| Your page | The `subscriptionManagementUrl` you sent on `/subscription/create` |

That is what `subscriptionManagementUrl` is for, and it is why the field should
point at something a customer can open in a desktop browser rather than an app
deeplink. Switching the setting is a request to your Waffo contact, not a
self-serve toggle.

There is no configuration that removes the management link from the emails
altogether. If you do not want customers routed anywhere by Waffo's emails, the
lever is to have the emails themselves turned off and send your own — see
[Subscription emails to your customers](/docs/en/support/subscription-notifications-faq).

## What can the customer actually see and do on the page?

**See** — the plan and its billing history, in more detail than the merchant
inquiry API returns:

| On the page | Notes |
| - | - |
| Plan description, amount and cycle | As configured on the subscription |
| Status | The subscription's current status |
| Bound payment methods | Masked card details and expiry where applicable |
| Per-period billing history | Period number, both currency/amount pairs, period start and end, a trial marker, and a customer-facing failure reason on failed periods |
| A receipt link per period | Present only on periods that were **collected for a non-zero amount** — so verification and zero-amount rows carry none |

**Do** — three things:

| Action | Availability |
| - | - |
| Cancel the subscription | While `ACTIVE` |
| Add a payment method, set a different default, reorder backups, delete a method | Card, Apple Pay and Google Pay subscriptions, while `ACTIVE`; the current default cannot be deleted |
| Simulate the next renewal | Sandbox only — see [Sandbox testing](/docs/en/support/sandbox-testing-faq) |

The payment-method rules and why adding one creates a zero-amount order are in
[Subscription retries & payment methods](/docs/en/support/subscription-retry-and-payment-methods-faq).

## Can I do the payment-method management from my own backend instead?

No. There is **no merchant-facing endpoint** that adds, replaces, reorders or
deletes the payment methods on a subscription. The public subscription API is
`create`, `inquiry`, `cancel`, `manage`, `change`, `change/inquiry` and
`update` — none of them touch the bound method list.

What you can do from your own product:

* Read the bound methods and the `canChangePaymentMethod` flag from
  `/api/v1/subscription/inquiry`, and render your own view of them.
* Send the customer to the hosted page to make the actual change.
* Move the customer to a different payment method by doing a **plan change**
  with a different `paymentInfo`, which re-authorises at checkout — see
  [Subscription plan changes](/docs/en/support/subscription-plan-change-faq).

So the pattern that works is: your UI shows the state, the hosted page performs
the mutation.

## Is cancellation on the page immediate, or at the end of the period?

**Immediate.** The customer confirms, the subscription moves to
`USER_CANCELLED`, and no further billing period is opened. There is no
end-of-period option on the page, and `/api/v1/subscription/cancel` is immediate
too.

That is worth stating plainly because it is the most common mismatch with a
merchant's own product rules: Waffo cancels the **billing**, not the
**entitlement**. If your policy is "keep the service until the paid period runs
out", you implement that on your side:

1. Listen for the subscription status notification.
2. On a cancellation, keep the customer's access until the end of the period they
   already paid for — you know that date from `nextPaymentDateTime` before the
   cancellation, or from the current period's end on the billing history.
3. Revoke access then.

The one place Waffo does perform an end-of-period retirement is a **plan change
with a future `startTime`**, which keeps the old plan running to the end of its
current period before retiring it. If your real requirement is "downgrade at the
end of the cycle", that is the mechanism — not cancel.

## What status change and webhook do I get when the customer cancels there?

The subscription moves to `USER_CANCELLED`, and you receive the **subscription
status notification** with that status. There is no separate "cancelled on the
hosted page" event.

Treat that webhook as the trigger, not your own records — you did not initiate
this cancellation, so until you process the notification your side still believes
the subscription is active. `USER_CANCELLED` versus `MERCHANT_CANCELLED` is how
you tell a customer-initiated churn from one you performed.

Money already collected is not touched by a cancellation. If you want to give the
customer the current period back, refund that period's charge — see
[Refunds](/docs/en/support/refund-faq).

## How far can the page be branded?

The page picks up the **checkout appearance and logo configured on the
subscription** — the same `cashierAppearance` and brand configuration you use for
checkout — so colours, typography and your logo carry through rather than the
customer landing on an unbranded page.

What is **not** configurable:

| | |
| - | - |
| Colours, background, typography, logo | Applied from your checkout appearance |
| Page copy and labels | Fixed. Not merchant-editable. |
| Hiding the cancel button, or any other control | Not supported |
| Adding your own fields or sections | Not supported |

So if your requirement is "the customer must not be able to cancel here", the
answer is not to configure the page — it is not to send the customer to it, and to
point Waffo's emails at your own management URL instead.

## What language is the page in?

The same resolution Waffo uses for the subscription's checkout and emails:

1. The cashier language you set on the subscription, if you set one.
2. Otherwise derived from the subscription's charging currency.
3. English as the fallback.

The language is baked into the link at the moment it is minted, so a link minted
before you set a cashier language keeps the old language until you mint a new
one. If your customers' language does not track their billing currency, set the
cashier language explicitly on the subscription rather than relying on the
derivation.

Plan titles and descriptions are **your** strings — the page renders the
description you sent on the subscription, so it appears in whatever language you
wrote it in, regardless of the page's own locale. If you localise your plan
names, send the localised string when you create the subscription.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.