# Let customers manage their own subscription

Every recurring plan created through Ultraner comes with a public, no-account page your customer can use to view or cancel their own subscription, the same way a Stripe customer manages billing from Stripe's own customer portal.

## What it is

When you create a recurring plan (mobile money, card, or PayPal, any channel), the response includes a `manage_url`, an unguessable link like `https://ultraner.com/manage/mng_xxxxx`. Anyone with that link can open it, see the plan's status, price and next billing date, and cancel it, without ever creating an Ultraner account or logging in. Ultraner hosts and builds the page, there is nothing to design or maintain on your side.

## Getting the link

`manage_url` comes back in the response the moment you create the plan, whether that's through the API directly or through a recurring payment link a customer checked out on:

```
POST /v1/recurring/plans
X-API-Key: uk_live_...

{ "name": "Premium plan", "mno_provider": "Vodacom",
  "account_number": "255712345678", "amount": 15000,
  "currency": "TZS", "interval_type": "monthly" }

// Response
{
  "success": true,
  "data": {
    "id": "UTRA-Rpl-...",
    "manage_url": "https://ultraner.com/manage/mng_xxxxx"
  }
}
```

## Where to put it

1. **On the confirmation screen** - show it right after checkout, so the customer can bookmark it while it's fresh in mind.
2. **In your own subscription/account page** - store `manage_url` against the customer's subscription in your own database, then render it as a "Manage subscription" link or button on their account page.
3. **In a confirmation email or SMS** - send it once at signup so the customer always has it on hand, even if they never visit your app again.

## Retrieving it later

`manage_url` is only ever returned once, at creation time. If you didn't save it then, or need to relink a returning customer to it, fetch the plan again with its id and the same field comes back:

```
GET /v1/recurring/plans/{id}
X-API-Key: uk_live_...

// Response includes the same manage_url field
```

## What customers see

The page shows the plan name, price, billing interval, current status (active, paused, cancelled, past due), and next renewal date. The customer can cancel immediately or at the end of the current period, and resume a plan that's cancelled-but-not-yet-expired. Mobile money plans can also be paused and resumed cleanly between cycles. Every action fires the matching webhook (`recurring.cancelled`, `recurring.activated`, etc.) to your own backend, so your app's own records stay in sync automatically, you never have to poll for it.

## Cancel at period end, and resume

Cancelling from the manage page defaults to **cancel at period end**: the subscription stays active and usable until its current period actually ends, and can be resumed anytime before then, with nothing charged. Mobile money and card both support this fully, mobile money through Ultraner's own scheduling, card through Stripe's native `cancel_at_period_end`.

**PayPal is the one exception** - its API has no cancel-at-period-end concept at all, only an immediate cancel. A PayPal subscription always ends right away when cancelled, and the manage page is upfront about that rather than promising a grace period PayPal can't actually give.

The authenticated API defaults the other way on purpose: `DELETE /v1/recurring/plans/{id}` cancels immediately by default (a programmatic caller almost always means "stop now"), opt into the gentler behavior with `?immediate=false`.

## Receipts

Every successful charge, on any channel, automatically issues a receipt, emailed and/or texted to whichever contact the customer has on file. Each billing-history row on the manage page carries a download (PDF) and resend-by-email button once its receipt exists.

## Security

The token in the URL is the credential, long, random, and unguessable, the same no-password-needed model Stripe's own billing portal links use. Anyone who has the exact link can manage that one subscription and nothing else, they can't browse to other plans, see your other customers, or access your account. Treat it like a password reset link: safe to email or text, but don't post it somewhere public.

---

Questions? Contact support@ultraner.com. Full API reference: https://ultraner.com/docs.md
