> ## 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.

# Subscription FAQ

> Answers to the most common questions about Waffo subscriptions: upgrades and downgrades, amount changes, failed deductions and retries, notifications, trials and user-side management.

This page answers the questions merchants ask most often about Waffo
subscriptions. Field-level contracts live in the
[Subscription API Specification](/docs/api-reference/introduction).

## How do I upgrade or downgrade a user's plan?

Call `/api/v1/subscription/change`. The change request creates a **new
subscription based on the original one**, and any remaining amount from the
original subscription is applied to the new one — you do not need to cancel
and re-create manually.

* Track the result with `/api/v1/subscription/change/inquiry`.
* Waffo also pushes a `SUBSCRIPTION_CHANGE_NOTIFICATION` when the change
  completes.

## What is the difference between `change`, `update`, and `manage`?

| API | Use it when |
| - | - |
| `/api/v1/subscription/change` | The user switches **plans** (upgrade / downgrade). Creates a new subscription and carries over the remaining amount. |
| `/api/v1/subscription/update` | You only need to adjust **amounts** on the existing subscription: the recurring amount, the trial-period amount, or per-period scheduled amounts. No plan switch, no new subscription. |
| `/api/v1/subscription/manage` | You want to hand the **end user** a hosted page to view or cancel their own subscription. Waffo returns a management URL you redirect the user to; each URL carries its own expiry, returned as `expiredAt`. |

Amount updates are validated against your contract limits.

## Can I charge different amounts in different periods?

Yes. Two mechanisms combine to cover tiered pricing and first-period offers:

* **Trial periods** — set `trialPeriodAmount` and `numberOfTrialPeriod` when
  creating the subscription. Custom trial granularity is supported via
  `trialPeriodType` and `trialPeriodInterval`.
* **Scheduled amounts** — configure per-period amounts for specific formal
  periods (for example, a discounted first period), either at creation or
  later through `/api/v1/subscription/update`.

If a period has no scheduled amount, the subscription's base `amount` applies.

## A deduction failed. What happens next?

Failed deductions are retried automatically according to the subscription's
retry strategy — you do not need to trigger retries yourself.

* Every payment attempt, including failure reason, timestamp and retry
  details, is pushed through the **subscription payment order notification**.
* If you only care about the final outcome of each billing period, listen to
  `SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION` instead — it fires once per
  period with the final result and skips intermediate retry events.

The specific retry schedule and caps depend on the retry strategy configured
for your contract. Contact integration support if you need the exact policy
for your account.

## Which subscription notifications should I listen to?

| Notification | Level | Use when |
| - | - | - |
| Subscription status notification | Subscription | You need to know the subscription lifecycle state (created, cancelled, expired). |
| Subscription payment order notification | Payment order | You need full visibility into every payment attempt, including failures and retries. |
| `SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION` | Billing period | You only need the final outcome of each period. |
| `SUBSCRIPTION_CHANGE_NOTIFICATION` | Change request | You need the result of an upgrade / downgrade. |
| `SUBSCRIPTION_UPDATE_NOTIFICATION` | Amount update | Sent to the subscription's `notifyUrl` after a successful `/api/v1/subscription/update` (including a seat add-on top-up once its charge succeeds). Carries the subscription as the inquiry API returns it, with the new amounts. |

For any notification, respond with `success` after processing. If Waffo
receives `failed` or `unknown`, Waffo retries the notification on a back-off
schedule spread over the following day; see
[Webhook retry](/docs/en/developer-docs/webhook/retry) for the schedule.

## How does a user cancel a subscription?

Two paths:

* **Merchant-initiated** — call `/api/v1/subscription/cancel`.
* **User-initiated** — redirect the user to the hosted management page
  obtained from `/api/v1/subscription/manage`, where they can view details
  and cancel.
* **Wallet-side** — if the user revokes the payment authorization inside their
  wallet app, the wallet notifies Waffo. If the revoked method was the only one
  on the subscription, the subscription is cancelled automatically; if a backup
  method is available, that method becomes the default instead. This is
  reported to you through the subscription status notification, so treat the
  webhook — not your own records — as the source of truth for whether a
  subscription is still active.

Once a subscription reaches a cancelled state no new billing period is opened.
Whether an already-pending retry is dropped immediately depends on a setting in
your contract — confirm it with integration support if that matters to you.

## Does Waffo support daily billing or cross-currency subscriptions?

Yes on both:

* `DAILY` is a supported `periodType`, alongside the other billing cycles.
* Cross-currency subscriptions are supported via the `userCurrency` field —
  the user pays in their local currency.

Payment-method-specific capabilities and limitations are listed in the
appendix of the
[Subscription API Specification](/docs/api-reference/introduction).

## What should I pass in `subscriptionManagementUrl`?

`subscriptionManagementUrl` is documented as required on subscription create
and you should always send it. Be aware that the server does **not** currently
reject a request that omits it — an omission will not surface as a validation
error, it will surface later as a missing link in the customer emails that are
routed to your page. Point it at a page the user can open **in a desktop
browser**. An app
deeplink is a poor choice here: users who open it on a PC may not be able to
reach the page at all. You have three options:

* Build your own authenticated subscription management page and pass its URL.
* Wrap the hosted page Waffo returns from `/api/v1/subscription/manage` in a
  page of your own and pass that.
* Use Waffo's hosted management page directly.

The page is a **feature entry point, not a step in the payment flow**. It is
not shown during the real-time transaction; you surface it after the
subscription payment succeeds — in the user's account area, an order
confirmation page, or anywhere else that suits your site.

## I received a subscription notification, but an immediate query says the subscription is not `ACTIVE`

Subscription state is **eventually consistent**. When a notification arrives,
the internal state update can still be settling, so a query fired immediately
afterwards may return a status that is not yet `ACTIVE`. That is a read timing
effect, not a failed subscription.

Handle it like this:

* Do not treat the first inquiry result as final. Re-query after a short pause.
* Prefer the subscription status notification as your trigger for state
  changes, and use the inquiry to confirm rather than to decide.

## Can the trial-period amount be the same as the regular amount?

No. At creation `trialPeriodAmount` must be **strictly lower** than `amount`;
an equal value is rejected with a parameter error whose message reads
`trial period amount should be less than subscription amount`. Zero is a valid
trial amount (a free trial), so the accepted range is `0 ≤ trialPeriodAmount <
amount`.

If the trial is meant to shift the billing calendar without changing the price,
do not configure a trial at all — use `startTime` to defer the first charge,
or `scheduledAmounts` to price specific early periods.


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