Skip to main content
This page describes the subscription (recurring billing) integration path for Waffo Subscription. After choosing this approach, work through the page in order to complete your integration. Each section covers only the decisions and gotchas for that step. Field definitions and enum values link to the relevant reference pages instead of being repeated here. For one-time payments, see the Direct API integration overview.

Choose a subscription integration approach

Waffo supports two subscription integration approaches. First choose who will manage the subscription: Waffo Subscription provides one integration approach for merchants. A renewal may be executed by Waffo or by the payment channel. For the small capability differences between payment methods, see the Subscription payment method comparison. A merchant-managed subscription does not use /api/v1/subscription/*. Your system owns the billing schedule, subscription status, failed-payment retries, plan changes, and cancellation. For each period, use a token obtained during card binding to initiate an MIT through ONE_TIME_PAYMENT. The card-binding docs already cover the token lifecycle, CIT verification, MIT request, and payment result confirmation, so those details are not repeated here. After you choose Waffo Subscription, follow the integration path below:

Confirm three things before you integrate

Whether subscriptions are available, and what each payment method actually supports, is ultimately determined by your contract configuration and the POST /api/v1/paymethodconfig/inquiry response.

Choose a subscription model

Waffo offers two subscription models. The core difference is how service and billing are handled after a renewal fails. Choosing the wrong one leaves your entitlement switching and billing rhythm out of step with what you expected, so decide before you integrate. Two questions to work out which one you are:
  1. Say the second period was due on 1 July, kept failing, and finally succeeded on 3 July. During those two days, do you suspend the customer’s entitlements (payment-first) or keep serving them (service-first)?
  2. If one period’s renewal fails for good, do you still want to charge for later periods? Stopping is payment-first; continuing is service-first.
Choose payment-first or service-first before integration and tell Waffo which model you want. Contact Waffo support if you need to confirm or change the model.
PIX supports service-first only; every other payment method supports both. See the Subscription payment method comparison.

Configure the billing period and trial

The period is expressed by combining productInfo.periodType with productInfo.periodInterval.
There is no YEARLY type. Express an annual subscription as MONTHLY with periodInterval: "12" — likewise 3 for quarterly, 6 for semi-annual, and 24 for two years.
The remaining period fields:
  • numberOfPeriod — total number of periods. Leave empty for an open-ended subscription.
  • trialPeriodAmount — the amount charged per trial period. Must be 0 or greater and less than the regular amount. Leave empty for no trial; set it to 0 for a free trial.
  • numberOfTrialPeriod — how many trial periods there are.
  • trialPeriodType / trialPeriodInterval — the period type and interval for the trial. These may differ from the regular period (for example a weekly trial before monthly billing); leave them empty to inherit the regular values. PIX requires the trial frequency to match the regular frequency.
  • scheduledAmounts — a per-period amount list whose elements are {period, amount}. Use it when amounts differ by period, such as a first-period discount or stepped pricing. Omit it when every period costs the same. This field is supported only by eligible Waffo-managed subscriptions; channel-managed subscriptions such as PIX and DANA do not support it.
For full field definitions, see Create Subscription.

Create a subscription and handle authorization

Call POST /api/v1/subscription/create to create a subscription. Beyond the period parameters, these fields cause the most trouble:
  • subscriptionRequest — the subscription idempotency key, which you generate. Reuse the same value when retrying a create request; see Idempotency.
  • currency and amount — subscriptions use currency and amount, not the orderCurrency and orderAmount used by one-time payments. Mixing up these field names is the most common integration error.
  • paymentInfo.payMethodType — optional. When provided, it filters candidates by payment method type. When omitted, Waffo applies no type filter. Waffo shows all eligible payment methods under your merchant contract only when paymentInfo.payMethodName is also omitted.
  • userInfo.userEmail — required. When you have no real email address, pass a unique fallback address derived from the user ID. Do not use placeholder values, and do not share one address across multiple users.
  • subscriptionManagementUrl — required, and it must be an authenticated page (not a public URL). Pass a web address rather than a deep link, because deep links cannot be opened on desktop. Use your own subscription management page, or wrap the URL returned by POST /api/v1/subscription/manage.
  • notifyUrl — your Webhook callback address; see Listen for notifications on this page.

Handle the authorization redirect

When subscriptionStatus in the response is AUTHORIZATION_REQUIRED, the customer has to complete authorization and you must redirect them to the authorization page. The address lives in subscriptionAction, which is a JSON string — parse it first, then read webUrl from it:
Do not read properties off subscriptionAction as if it were an object — it is a string and must be JSON-parsed first. The same handling applies to the subscription inquiry, subscription change, and change inquiry responses.

Subscription status and what you should do

A subscription has 8 statuses. For what to do in each one, see the Payment lifecycle; for which ones are final, see the Data reference.
Do not treat the synchronous create response as the final subscription status. Activation, cancellation, and closure all arrive via Webhook — or confirm them yourself with POST /api/v1/subscription/inquiry.

Listen for notifications

Subscriptions involve three notifications; subscribe to the ones that match the granularity you care about. For when each one fires, what it suits, and the recommended combinations, see Webhook event types. The key constraint: SUBSCRIPTION_STATUS_NOTIFICATION and SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION are both dispatched asynchronously and arrive in no guaranteed order, so never drive your business state machine off callback arrival order. For the correct approach (idempotent deduplication, and querying the final status after either callback arrives), see Webhook best practices.

Renewal failures and retries

Who retries a failed renewal—Waffo or the payment channel—depends on the renewal management type. For Waffo-managed subscriptions, Waffo retries the current period’s charge automatically — you do not need to implement retries yourself:
  • The retry policy is configured per billing cycle, and each tier covers a maximum number of attempts and a retry interval.
  • The retry interval is measured in days. There is no hour-level retry interval configuration.
  • Without customization, Waffo retries once per day after the current-period charge first fails, for up to five retry attempts. To customize the attempt limit or interval, contact your Waffo account manager or technical support; you cannot change this policy through API parameters.
  • Your subscription model determines both the next-period baseline after a retry succeeds and whether later periods are still charged after retries are exhausted. See Subscription payment method comparison for the complete Waffo-managed renewal timing rules.
For channel-managed subscriptions, the payment channel applies its own retry rules. PIX and DANA use wallet-side retry rules and do not support merchant customization. See Subscription payment method comparison for details.
For Waffo-managed subscriptions, mind the notification granularity: every failed attempt during retries sends a PAYMENT_NOTIFICATION. If you only care about each period’s final result and not the intermediate retries, subscribe to SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION instead.

Change, update, and cancel

These are three different operations on three different endpoints — do not mix them up:

Common amount-update scenarios

update supports only ACTIVE, Waffo-managed subscriptions. Every request must include at least one of amount, productInfo.trialPeriodAmount, or productInfo.scheduledAmounts. Even when you add topupInfo, include the target amount to apply after the top-up succeeds. A direct amount update affects future charges; the current-period order already exists and cannot be changed directly. Example request for a current-period seat add-on:
topupAmount is the current-period difference you calculate and must be greater than 0; amount is the new total for later periods after the top-up succeeds. topupRequest is the top-up idempotency key and must be reused when retrying the same request. When the response has topupInfo.topupStatus set to AUTHORIZATION_REQUIRED, parse topupInfo.topupAction as a JSON string and redirect the customer to its webUrl. A subscription can have only one top-up in progress at a time. With some payment methods, customers can cancel on the payment method’s own side (Apple Wallet, Google Pay, and the PayPay app, for example). That cancellation is reported back to Waffo and surfaces as CHANNEL_CANCELLED or USER_CANCELLED. For which payment methods support customer-side cancellation, see the Subscription payment method comparison.

Sandbox and acceptance

1

First-period payment

Works the same as a one-time payment — complete it on the cashier page.
2

Simulate renewals

Call POST /api/v1/subscription/manage to get the management page URL, open it, and use the “simulate next payment success” and “simulate next payment failure” buttons to step through periods. For the procedure, see Sandbox and testing and the Sandbox simulator.
3

Acceptance

Run the subscription acceptance cases from the Integration acceptance criteria, fill in the subscription acceptance case template, and submit it to your Waffo technical integration group.
Before going live, confirm at minimum: both the success and failure paths for the first period, signature verification on the subscription status and subscription payment notifications, matching each period order by subscriptionRequest plus period number, and not closing subscriptions yourself on an Unknown status.