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

# Renewal charges

> How the DVM processes recurring subscription charges.

## Overview

A Renewal charge is a payment that repeats on a set schedule — monthly, annually, or otherwise. It's linked to an ongoing subscription offer rather than a one-time purchase.

When you create a Subscription Offer in the DVM, you define a billing plan that determines the subscription duration and how frequently it renews. The DVM uses this plan to drive all charge activity for that offer automatically — from the first charge when a consumer is provisioned, through every subsequent renewal for the lifetime of the subscription.

Behind the scenes, the platform manages the full complexity of subscription billing, from renewals and plan changes to cancellations and payment retries. Charges stay accurate, billing stays on track, and consumers keep uninterrupted access to their services.

***

## When renewal charges are issued

There are four charge scenarios your billing system will receive for a Subscription Offer:

<CardGroup cols={2}>
  <Card title="First Bill" icon="circle-play">
    Issued when a consumer is first provisioned with an Offer and the billing plan starts.

    This is the consumer's initial charge and marks the beginning of their subscription billing lifecycle.`billType: FIRST_BILL`
  </Card>

  <Card title="Renewal" icon="rotate">
    Issued automatically at the end of each billing period, in line with the renewal frequency defined in the Offer plan.

    The consumer is charged the full subscription amount for the next period. `billType: RENEWAL`
  </Card>

  <Card title="Renewal after Upgrade" icon="circle-up">
    When a consumer has upgraded to a higher product tier mid-cycle, future renewal charge reflects the new, higher price.

    The charge `lineItems` will include both the original offer amount and an `OFFER_ENTITLEMENT_TIER_DELTA` reflecting the price difference. `billType: RENEWAL`
  </Card>

  <Card title="Renewal after Downgrade" icon="circle-down">
    When a consumer has downgraded to a lower product tier mid-cycle, future renewal charge reflects the new, lower price.

    The charge`lineItems` will include the original offer amount and a negative `OFFER_ENTITLEMENT_TIER_DELTA` for the price reduction. `billType: RENEWAL`
  </Card>
</CardGroup>

<Info>
  Mid-cycle upgrades also trigger an immediate **pro-rated charge** (`billType: PRO_RATED_CHARGE`) to collect the price difference for the remaining days in the current billing period. See [Pro-ration](/billing-and-charging/pro-ration) for full details.
</Info>

***

## Charge request examples

Each scenario results in a `POST /charges` request to your billing system. Below are examples of what each looks like.

<AccordionGroup>
  <Accordion title="First Bill">
    Sent when a consumer is first provisioned. The `billType` is `FIRST_BILL` and `isRetry` is `false`.

    ```json theme={null}
    {
      "requestId": "218958bf-6eaf-4b21-bcba-40982aa7eb51",
      "billEffectiveDate": "2026-01-01T01:00:00.000Z",
      "billType": "FIRST_BILL",
      "billId": "347d18b7-3166-428c-b0c5-293ab25bf28b",
      "chargeId": "a6d6654f-3dfa-4db8-8953-a81a13256fd4",
      "chargeAttempt": 0,
      "isRetry": false,
      "amount": 1999,
      "currency": "USD",
      "consumer": {
        "consumerIdentifier": "RFBNZ2MU3Y35OA5GNNNGETK6JTEVRYVB",
        "billingIdentifier": "BWNMJXEDAO7HTK6Q4SBAOEJMPGURUB3K"
      },
      "resourceType": "CONSUMER_OFFER",
      "consumerOffer": {
        "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51",
        "offerId": "7560fca0-d8a9-4124-a172-924debec874e",
        "entitlements": [
          {
            "entitlementId": "b0163d06-1fa3-4c9b-a298-29635ca7151d",
            "contentProviderId": "NETFLIX",
            "productId": "Netflix",
            "productTierKey": "NETFLIX_STD"
          }
        ]
      },
      "billingDetails": {
        "planType": "SUBSCRIPTION",
        "billingPeriod": {
          "phaseType": "FULL_PRICE",
          "duration": "P1M",
          "startDate": "2026-01-01T01:00:00.000Z",
          "endDate": "2026-02-01T00:59:59.999Z"
        }
      },
      "lineItems": [
        {
          "lineItemType": "OFFER",
          "quantity": 1,
          "amount": 1999,
          "currency": "USD",
          "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51"
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Renewal">
    Sent at the end of each billing period. Identical structure to First Bill but with `billType: RENEWAL` and updated `billingPeriod` dates reflecting the new cycle.

    ```json theme={null}
    {
      "requestId": "a95ec4ff-ac07-40ac-905c-0bbfdfacf409",
      "billEffectiveDate": "2026-02-01T01:00:00.000Z",
      "billType": "RENEWAL",
      "billId": "b0060ac6-9464-4297-9213-a3d8139e1438",
      "chargeId": "0b6d75ac-75ba-4a29-89a4-c2ba34f7712c",
      "chargeAttempt": 0,
      "isRetry": false,
      "amount": 1999,
      "currency": "USD",
      "consumer": {
        "consumerIdentifier": "RFBNZ2MU3Y35OA5GNNNGETK6JTEVRYVB",
        "billingIdentifier": "BWNMJXEDAO7HTK6Q4SBAOEJMPGURUB3K"
      },
      "resourceType": "CONSUMER_OFFER",
      "consumerOffer": {
        "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51",
        "offerId": "7560fca0-d8a9-4124-a172-924debec874e",
        "entitlements": [
          {
            "entitlementId": "b0163d06-1fa3-4c9b-a298-29635ca7151d",
            "contentProviderId": "NETFLIX",
            "productId": "Netflix",
            "productTierKey": "NETFLIX_STD"
          }
        ]
      },
      "billingDetails": {
        "planType": "SUBSCRIPTION",
        "billingPeriod": {
          "phaseType": "FULL_PRICE",
          "duration": "P1M",
          "startDate": "2026-02-01T01:00:00.000Z",
          "endDate": "2026-03-01T00:59:59.999Z"
        }
      },
      "lineItems": [
        {
          "lineItemType": "OFFER",
          "quantity": 1,
          "amount": 1999,
          "currency": "USD",
          "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51"
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Renewal after Upgrade">
    When a consumer has upgraded their offer to a higher tier product, when the subscription renews, the total renewal charge amount includes the additional charge amount for the Upgrade. In this example the total renewal charge after the upgrade is \$26.99.

    This total amount is itemised under `lineItems`:

    * `OFFER =` \$19.99, which is the original Offer price amount
    * `OFFER_ENTITLEMENT_TIER_DELTA` = \$7.00, which is the additional price for the upgrade

    ```json theme={null}
    {
      "requestId": "f8e7d6c5-b4a3-4c2b-8d1e-9f0a1b2c3dff",
      "billEffectiveDate": "2026-03-01T01:00:00.000Z",
      "billType": "RENEWAL",
      "billId": "a56c91f6-1357-42d0-9818-5198d7e54902",
      "chargeId": "c699aa49-35ea-4a23-9c3e-4479413db91d",
      "chargeAttempt": 0,
      "isRetry": false,
      "amount": 2699,
      "currency": "USD",
      "consumer": {
        "consumerIdentifier": "RFBNZ2MU3Y35OA5GNNNGETK6JTEVRYVB",
        "billingIdentifier": "BWNMJXEDAO7HTK6Q4SBAOEJMPGURUB3K"
      },
      "resourceType": "CONSUMER_OFFER",
      "consumerOffer": {
        "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51",
        "offerId": "7560fca0-d8a9-4124-a172-924debec874e",
        "entitlements": [
          {
            "entitlementId": "b0163d06-1fa3-4c9b-a298-29635ca7151d",
            "contentProviderId": "NETFLIX",
            "productId": "Netflix",
            "productTierKey": "NETFLIX_PREMIUM"
          }
        ]
      },
      "billingDetails": {
        "planType": "SUBSCRIPTION",
        "billingPeriod": {
          "phaseType": "FULL_PRICE",
          "duration": "P1M",
          "startDate": "2026-03-01T01:00:00.000Z",
          "endDate": "2026-04-01T00:59:59.999Z"
        }
      },
      "lineItems": [
        {
          "lineItemType": "OFFER",
          "quantity": 1,
          "amount": 1999,
          "currency": "USD",
          "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51"
        },
        {
          "lineItemType": "OFFER_ENTITLEMENT_TIER_DELTA",
          "quantity": 1,
          "amount": 700,
          "currency": "USD",
          "entitlementId": "b0163d06-1fa3-4c9b-a298-29635ca7151d"
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Renewal after Downgrade">
    When a consumer has downgraded their offer to a lower tier product, when the subscription renews, the total renewal charge amount reflects the price reduction for the Downgrade. In this example the total renewal charge after the downgrade is \$8.99.

    This total amount is itemised under `lineItems`:

    * `OFFER =` \$19.99, which is the original Offer price amount
    * `OFFER_ENTITLEMENT_TIER_DELTA` = -\$11.00, which is the price reduction for the downgrade

    ```json theme={null}
    {
      "requestId": "b8d579e9-c937-4be9-a1de-eb5214c50ab8",
      "billEffectiveDate": "2026-04-01T01:00:00.000Z",
      "billType": "RENEWAL",
      "billId": "f0c4f625-e9f4-4ed6-92b2-fca4570d550f",
      "chargeId": "32dfaaeb-a5ef-4379-a634-3503320f2c81",
      "chargeAttempt": 0,
      "isRetry": false,
      "amount": 899,
      "currency": "USD",
      "consumer": {
        "consumerIdentifier": "RFBNZ2MU3Y35OA5GNNNGETK6JTEVRYVB",
        "billingIdentifier": "BWNMJXEDAO7HTK6Q4SBAOEJMPGURUB3K"
      },
      "resourceType": "CONSUMER_OFFER",
      "consumerOffer": {
        "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51",
        "offerId": "7560fca0-d8a9-4124-a172-924debec874e",
        "entitlements": [
          {
            "entitlementId": "b0163d06-1fa3-4c9b-a298-29635ca7151d",
            "contentProviderId": "NETFLIX",
            "productId": "Netflix",
            "productTierKey": "NETFLIX_STD_ADS"
          }
        ]
      },
      "billingDetails": {
        "planType": "SUBSCRIPTION",
        "billingPeriod": {
          "phaseType": "FULL_PRICE",
          "duration": "P1M",
          "startDate": "2026-04-01T01:00:00.000Z",
          "endDate": "2026-05-01T00:59:59.999Z"
        }
      },
      "lineItems": [
        {
          "lineItemType": "OFFER",
          "quantity": 1,
          "amount": 1999,
          "currency": "USD",
          "consumerOfferId": "338d31e1-a289-40dd-beff-ab41c1fc5f51"
        },
        {
          "lineItemType": "OFFER_ENTITLEMENT_TIER_DELTA",
          "quantity": 1,
          "amount": -1100,
          "currency": "USD",
          "entitlementId": "b0163d06-1fa3-4c9b-a298-29635ca7151d"
        }
      ]
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Key fields explained

These are the most important fields to understand across all charge request types:

<ResponseField name="billType" type="string" required>
  Identifies what triggered the charge. One of `FIRST_BILL` (initial provisioning charge), `RENEWAL` (scheduled recurring charge), or `PRO_RATED_CHARGE` (mid-cycle upgrade charge).
</ResponseField>

<ResponseField name="billId" type="string" required>
  A unique identifier for the bill. If a charge fails and is retried, all retry attempts share the same `billId` — only the `chargeId` changes. Use this for reconciliation.
</ResponseField>

<ResponseField name="chargeId" type="string" required>
  A unique identifier for this specific charge transaction. Each attempt — including retries — gets its own `chargeId`. Echo this back in your response.
</ResponseField>

<ResponseField name="isRetry / chargeAttempt" type="boolean / integer" required>
  `isRetry: true` means this is a retry of a previously failed charge. `chargeAttempt` tells you which attempt this is (`0` = first attempt, `1` = first retry, etc.). Use `billId` to deduplicate against any prior attempt.
</ResponseField>

<ResponseField name="amount" type="integer" required>
  The total charge amount in **minor currency units** (e.g. `1999` = \$19.99 USD). For renewals after a tier change, this is the new net total, not the base price.
</ResponseField>

<ResponseField name="lineItems" type="array" required>
  The itemised breakdown of the charge. A standard renewal has a single `OFFER` line item. Renewals after a tier change include an additional `OFFER_ENTITLEMENT_TIER_DELTA` line item — positive for upgrades, negative for downgrades. The `entitlementId` on this line item tells you which product entitlement changed.
</ResponseField>

<ResponseField name="billingDetails.billingPeriod" type="object" required>
  The period this charge covers, including `startDate`, `endDate`, `duration` (ISO 8601 format, e.g. `P1M` for monthly), and `phaseType` (`FREE`, `DISCOUNT`, or `FULL_PRICE`). Useful for matching charges to subscription periods in your records.
</ResponseField>

***

## How to respond

Your billing system must respond to every charge request with a `200` status and a JSON body indicating whether the charge was processed or declined.

### Approved

```json theme={null}
{
  "requestId": "a95ec4ff-ac07-40ac-905c-0bbfdfacf409",
  "responseCode": "APPROVED"
}
```

### Declined

```json theme={null}
{
  "requestId": "a95ec4ff-ac07-40ac-905c-0bbfdfacf409",
  "responseCode": "DECLINED",
  "reason": "USER_INSUFFICIENT_CREDIT",
  "reasonDescription": "Insufficient credit"
}
```

### Decline reason codes

| Reason code | Meaning | Bango will retry? |
| - | - | - |
| `DENIED` | General denial — no more specific reason available | ❌ No |
| `USER_INVALID` | Consumer identifier not recognised or account closed | ❌ No |
| `USER_BARRED` | Consumer is permanently barred from this payment method | ❌ No |
| `USER_SUSPENDED` | Consumer account is temporarily suspended | ✅ Yes |
| `USER_NOT_ENABLED` | Consumer not yet enabled for this payment method | ✅ Yes |
| `USER_INSUFFICIENT_CREDIT` | Consumer has insufficient funds or credit | ✅ Yes |
| `USER_SPEND_LIMIT_EXCEEDED` | Consumer has hit a spend limit (daily/weekly/monthly) | ✅ Yes |
| `ALREADY_IN_PROGRESS` | A charge with the same `chargeId` is already being processed | ⏳ Bango will wait before retrying |

<Warning>
  Always return a `reason` when declining. Without it, Bango may treat the response as an error and apply retry logic regardless of the actual decline reason.
</Warning>

***

## How we deal with failure

* **Restarts** — Scheduled charges continue even if the service is temporarily unavailable. Once back online, processing resumes automatically with no missed payments.
* **Retries** — If a charge is declined with a retryable reason code, Bango will automatically retry using a Fibonacci backoff schedule for up to 24 hours. See [Billing Retry Schedule](/billing-and-charging/billing-retry-schedule) for full details.
* **External dependencies** — Temporary delays in connected systems won't cause scheduled charges to be missed.

***

## Key takeaways

<Card title="Revenue is protected" icon="shield-check" horizontal>
  Retry logic and persistent scheduling mean that transient failures do not become lost revenue. The platform keeps trying until a charge succeeds or the plan is explicitly closed.
</Card>

<Card title="Accurate invoices" icon="file-invoice" horizontal>
  Every charge produces an invoice that reflects exactly what was charged and why. Pro-rated adjustments and tier changes are itemised clearly in `lineItems`, giving consumers and care teams a precise record to refer to.
</Card>

<Card title="Scales without limit" icon="chart-line" horizontal>
  High volumes of renewals don't affect the experience for other customers. Charges continue to be processed as expected.
</Card>

<Card title="Partners and teams stay informed" icon="bell" horizontal>
  Key events in the recurring charge lifecycle — invoice issued, payment taken, payment failed, plan changed — are surfaced as real-time notifications. Resellers, operations, and customer-facing teams can all be kept in the loop automatically.
</Card>
